seg - Version 1.1.1.0

Version Notes

Updates to AddedToBasket event capture, tag management, order status management, multiple store-front capability and improved historical data export to Seg.

Download this release

Release Info

Developer Seg
Extension seg
Version 1.1.1.0
Comparing to
See all releases


Code changes from version 1.0.0.0 to 1.1.1.0

Files changed (37) hide show
  1. app/code/community/Koan/.DS_Store +0 -0
  2. app/code/community/Koan/Seg/Block/Adminhtml/Exporter.php +45 -11
  3. app/code/community/Koan/Seg/Block/Adminhtml/Exporter/Grid.php +25 -0
  4. app/code/community/Koan/Seg/Block/Adminhtml/Exporter/Grid/Renderer/Log.php +18 -0
  5. app/code/community/Koan/Seg/Block/Adminhtml/Exporter/Grid/Renderer/Status.php +3 -1
  6. app/code/community/Koan/Seg/Block/Header.php +3 -1
  7. app/code/community/Koan/Seg/Block/Track.php +42 -5
  8. app/code/community/Koan/Seg/Helper/Data.php +146 -56
  9. app/code/community/Koan/Seg/Model/Batch/Log.php +10 -0
  10. app/code/community/Koan/Seg/Model/Batch/Status.php +24 -4
  11. app/code/community/Koan/Seg/Model/Config/Source/Websites.php +21 -0
  12. app/code/community/Koan/Seg/Model/Guid/Validator.php +15 -0
  13. app/code/community/Koan/Seg/Model/Observer.php +4 -2
  14. app/code/community/Koan/Seg/Model/Resource/Batch/Log.php +9 -0
  15. app/code/community/Koan/Seg/Model/Resource/Batch/Log/Collection.php +10 -0
  16. app/code/community/Koan/Seg/Model/Resource/Log/Status.php +9 -0
  17. app/code/community/Koan/Seg/Model/Resource/Log/Status/Collection.php +10 -0
  18. app/code/community/Koan/Seg/Model/Seg/Basket.php +48 -0
  19. app/code/community/Koan/Seg/Model/Seg/Client.php +18 -30
  20. app/code/community/Koan/Seg/Model/Seg/Exporter.php +281 -38
  21. app/code/community/Koan/Seg/Model/Seg/Order/Line.php +24 -20
  22. app/code/community/Koan/Seg/Model/Seg/Product.php +20 -18
  23. app/code/community/Koan/Seg/Model/Seg/Quote/Line.php +28 -19
  24. app/code/community/Koan/Seg/Model/Seg/Range.php +25 -5
  25. app/code/community/Koan/Seg/Model/Singlepayload/Exception.php +7 -0
  26. app/code/community/Koan/Seg/Model/System/Config/Source/Attributes.php +96 -0
  27. app/code/community/Koan/Seg/controllers/Adminhtml/SegController.php +53 -21
  28. app/code/community/Koan/Seg/etc/adminhtml.xml +2 -0
  29. app/code/community/Koan/Seg/etc/config.xml +4 -1
  30. app/code/community/Koan/Seg/etc/system.xml +40 -11
  31. app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.0-1.0.0.1.php +1 -0
  32. app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.1-1.0.0.2.php +1 -0
  33. app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.2-1.0.0.3.php +16 -0
  34. app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.3-1.0.0.4.php +30 -0
  35. app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.4-1.0.0.5.php +14 -0
  36. app/design/adminhtml/default/default/layout/seg.xml +1 -1
  37. package.xml +52 -31
app/code/community/Koan/.DS_Store DELETED
Binary file
app/code/community/Koan/Seg/Block/Adminhtml/Exporter.php CHANGED
@@ -7,12 +7,22 @@ class Koan_Seg_Block_Adminhtml_Exporter extends Mage_Adminhtml_Block_Widget_Grid
7
  {
8
  $orderBatchUrl = Mage::getModel('adminhtml/url')->getUrl(
9
  'adminhtml/seg/createBatchOrder',
10
- array('order_date_from' => 'NO_FILTER')
11
  );
12
 
13
  return $orderBatchUrl;
14
  }
15
 
 
 
 
 
 
 
 
 
 
 
16
  public function __construct()
17
  {
18
  $this->_controller = 'adminhtml_exporter';
@@ -22,11 +32,7 @@ class Koan_Seg_Block_Adminhtml_Exporter extends Mage_Adminhtml_Block_Widget_Grid
22
  parent::__construct();
23
  $this->_removeButton('add');
24
 
25
- $customerUrl = Mage::getModel('adminhtml/url')->getUrl(
26
- 'adminhtml/seg/createBatchCustomer',
27
- null
28
- );
29
-
30
 
31
  $this->addButton(
32
  'start_order_batch',
@@ -42,20 +48,38 @@ class Koan_Seg_Block_Adminhtml_Exporter extends Mage_Adminhtml_Block_Widget_Grid
42
  'start_customer_batch',
43
  array(
44
  'label' => Mage::helper('koan_seg')->__('Start New Customers Export Batch'),
45
- 'onclick' => 'setLocation(\'' . $customerUrl . '\')',
46
  'class' => 'add',
47
  'style' => 'margin-right:20px;'
48
  )
49
  );
50
  }
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  private function _getDateSelectorHtml()
53
  {
54
  $element = new Varien_Data_Form_Element_Date(
55
  array(
56
  'name' => 'order_date_filter',
57
  'label' => Mage::helper('koan_seg')->__('Date'),
58
- 'tabindex' => 1,
59
  'image' => $this->getSkinUrl('images/grid-cal.gif'),
60
  'format' => Varien_Date::DATE_INTERNAL_FORMAT,
61
  'value' => null
@@ -68,16 +92,26 @@ class Koan_Seg_Block_Adminhtml_Exporter extends Mage_Adminhtml_Block_Widget_Grid
68
  return '<label for="order_date_filter">Filter orders from date: </label>' . $element->getElementHtml();
69
  }
70
 
71
- private function _getDateFilterJs()
72
  {
73
  $js = '<script>';
 
74
  $js .= 'function getOrderBatchUrl(){';
75
  $js .= 'var url=\'' . $this->_getOrderBatchUrl() . '\';';
76
  $js .= 'var dtFilter = $("order_date_filter").getValue();';
77
  $js .= 'if(dtFilter){url = url.sub("NO_FILTER", JSON.stringify({"date":dtFilter}));}';
78
- //$js .= 'if(dtFilter){url = url.sub("NO_FILTER", dtFilter);}';
 
 
 
 
 
 
 
 
79
  $js .= 'setLocation(url);';
80
  $js .= '}';
 
81
  $js .= '</script>';
82
 
83
  return $js;
@@ -86,7 +120,7 @@ class Koan_Seg_Block_Adminhtml_Exporter extends Mage_Adminhtml_Block_Widget_Grid
86
  protected function _toHtml()
87
  {
88
  $html = parent::_toHtml();
89
- $html .= $this->_getDateFilterJs();
90
 
91
  return $html;
92
  }
7
  {
8
  $orderBatchUrl = Mage::getModel('adminhtml/url')->getUrl(
9
  'adminhtml/seg/createBatchOrder',
10
+ array('order_date_from' => 'NO_FILTER', 'website' => 'WEBSITE_ID')
11
  );
12
 
13
  return $orderBatchUrl;
14
  }
15
 
16
+ private function _getCustomerBatchUrl()
17
+ {
18
+ $customerUrl = Mage::getModel('adminhtml/url')->getUrl(
19
+ 'adminhtml/seg/createBatchCustomer',
20
+ array('website' => 'WEBSITE_ID')
21
+ );
22
+
23
+ return $customerUrl;
24
+ }
25
+
26
  public function __construct()
27
  {
28
  $this->_controller = 'adminhtml_exporter';
32
  parent::__construct();
33
  $this->_removeButton('add');
34
 
35
+ $this->setTemplate('seg/grid/container.phtml');
 
 
 
 
36
 
37
  $this->addButton(
38
  'start_order_batch',
48
  'start_customer_batch',
49
  array(
50
  'label' => Mage::helper('koan_seg')->__('Start New Customers Export Batch'),
51
+ 'onclick' => 'getCustomerBatchUrl()',
52
  'class' => 'add',
53
  'style' => 'margin-right:20px;'
54
  )
55
  );
56
  }
57
 
58
+ public function getWebsiteSelectorHtml()
59
+ {
60
+ $websites = Mage::getSingleton('koan_seg/config_source_websites')->toOptionArray();
61
+ $element = new Varien_Data_Form_Element_Select(
62
+ array(
63
+ 'name' => 'website',
64
+ 'label' => Mage::helper('koan_seg')->__('Website'),
65
+ 'tabindex' => 1,
66
+ 'values' => $websites
67
+ )
68
+ );
69
+
70
+ $element->setForm(new Varien_Data_Form());
71
+ $element->setId('websites_filter');
72
+
73
+ return $element->getElementHtml();
74
+ }
75
+
76
  private function _getDateSelectorHtml()
77
  {
78
  $element = new Varien_Data_Form_Element_Date(
79
  array(
80
  'name' => 'order_date_filter',
81
  'label' => Mage::helper('koan_seg')->__('Date'),
82
+ 'tabindex' => 2,
83
  'image' => $this->getSkinUrl('images/grid-cal.gif'),
84
  'format' => Varien_Date::DATE_INTERNAL_FORMAT,
85
  'value' => null
92
  return '<label for="order_date_filter">Filter orders from date: </label>' . $element->getElementHtml();
93
  }
94
 
95
+ private function _getFiltersJs()
96
  {
97
  $js = '<script>';
98
+
99
  $js .= 'function getOrderBatchUrl(){';
100
  $js .= 'var url=\'' . $this->_getOrderBatchUrl() . '\';';
101
  $js .= 'var dtFilter = $("order_date_filter").getValue();';
102
  $js .= 'if(dtFilter){url = url.sub("NO_FILTER", JSON.stringify({"date":dtFilter}));}';
103
+ $js .= 'var website = $("websites_filter").getValue();';
104
+ $js .= 'if(website){url = url.sub("WEBSITE_ID", website);}';
105
+ $js .= 'setLocation(url);';
106
+ $js .= '}';
107
+
108
+ $js .= 'function getCustomerBatchUrl(){';
109
+ $js .= 'var url=\'' . $this->_getCustomerBatchUrl() . '\';';
110
+ $js .= 'var website = $("websites_filter").getValue();';
111
+ $js .= 'if(website){url = url.sub("WEBSITE_ID", website);}';
112
  $js .= 'setLocation(url);';
113
  $js .= '}';
114
+
115
  $js .= '</script>';
116
 
117
  return $js;
120
  protected function _toHtml()
121
  {
122
  $html = parent::_toHtml();
123
+ $html .= $this->_getFiltersJs();
124
 
125
  return $html;
126
  }
app/code/community/Koan/Seg/Block/Adminhtml/Exporter/Grid.php CHANGED
@@ -16,6 +16,11 @@ class Koan_Seg_Block_Adminhtml_Exporter_Grid extends Mage_Adminhtml_Block_Widget
16
  protected function _prepareCollection()
17
  {
18
  $collection = Mage::getResourceModel('koan_seg/batch_status_collection');
 
 
 
 
 
19
  $this->setCollection($collection);
20
  return parent::_prepareCollection();
21
  }
@@ -29,6 +34,19 @@ class Koan_Seg_Block_Adminhtml_Exporter_Grid extends Mage_Adminhtml_Block_Widget
29
  'index' => 'id',
30
  ));
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  $this->addColumn('entity_type', array(
33
  'header' => Mage::helper('koan_seg')->__('Entity Type'),
34
  'align' => 'left',
@@ -69,6 +87,13 @@ class Koan_Seg_Block_Adminhtml_Exporter_Grid extends Mage_Adminhtml_Block_Widget
69
  'index' => 'comment',
70
  ));
71
 
 
 
 
 
 
 
 
72
  return parent::_prepareColumns();
73
  }
74
 
16
  protected function _prepareCollection()
17
  {
18
  $collection = Mage::getResourceModel('koan_seg/batch_status_collection');
19
+ $collection->getSelect()->join(
20
+ 'core_website', 'core_website.website_id = main_table.website_id',
21
+ array('website_name' => 'name')
22
+ );
23
+
24
  $this->setCollection($collection);
25
  return parent::_prepareCollection();
26
  }
34
  'index' => 'id',
35
  ));
36
 
37
+ $this->addColumn('website', array(
38
+ 'header' => Mage::helper('koan_seg')->__('Website'),
39
+ 'align' => 'left',
40
+ 'index' => 'website_name',
41
+ ));
42
+
43
+ $this->addColumn('filter', array(
44
+ 'header' => Mage::helper('sales')->__('Orders filtered from Date:'),
45
+ 'index' => 'filter',
46
+ 'type' => 'date',
47
+ 'filter' => false
48
+ ));
49
+
50
  $this->addColumn('entity_type', array(
51
  'header' => Mage::helper('koan_seg')->__('Entity Type'),
52
  'align' => 'left',
87
  'index' => 'comment',
88
  ));
89
 
90
+ $this->addColumn('edit', array(
91
+ 'header' => Mage::helper('koan_seg')->__('View Log'),
92
+ 'align' => 'right',
93
+ 'width' => '200px',
94
+ 'renderer' => 'koan_seg/adminhtml_exporter_grid_renderer_log',
95
+ ));
96
+
97
  return parent::_prepareColumns();
98
  }
99
 
app/code/community/Koan/Seg/Block/Adminhtml/Exporter/Grid/Renderer/Log.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Block_Adminhtml_Exporter_Grid_Renderer_Log extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
4
+ {
5
+
6
+ public function render(Varien_Object $row)
7
+ {
8
+ $id = $row->getId();
9
+
10
+ $url = $this->getUrl('*/seg/log', array('id' => $id));
11
+
12
+ $action = "popWin(this.href,'_blank','width=1024,height=700,resizable=1,scrollbars=1');return false;";
13
+
14
+ $html = sprintf('<a onclick="%s" href="%s" target="_blank">%s</a>',$action, $url, $this->__('View Log'));
15
+ return $html;
16
+
17
+ }
18
+ }
app/code/community/Koan/Seg/Block/Adminhtml/Exporter/Grid/Renderer/Status.php CHANGED
@@ -10,7 +10,9 @@ class Koan_Seg_Block_Adminhtml_Exporter_Grid_Renderer_Status extends Mage_Adminh
10
  Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_STARTING => 'Export starting in progress',
11
  Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_PROCESSING_ROWS => 'Processing rows',
12
  Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_COMPLETE => 'Export completed',
13
- Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR => 'Error'
 
 
14
  );
15
 
16
  return isset($statuses[$status]) ? $statuses[$status] : $status;
10
  Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_STARTING => 'Export starting in progress',
11
  Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_PROCESSING_ROWS => 'Processing rows',
12
  Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_COMPLETE => 'Export completed',
13
+ Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR => 'Error',
14
+ Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_NEED_RETRY => 'Pending Retry'
15
+
16
  );
17
 
18
  return isset($statuses[$status]) ? $statuses[$status] : $status;
app/code/community/Koan/Seg/Block/Header.php CHANGED
@@ -11,7 +11,9 @@ class Koan_Seg_Block_Header extends Mage_Core_Block_Template
11
  {
12
  protected function _beforeToHtml()
13
  {
14
- $websiteId = $this->helper('koan_seg')->getWebsiteId();
 
 
15
  if (empty($websiteId)) {
16
  $this->_template = null;
17
  }
11
  {
12
  protected function _beforeToHtml()
13
  {
14
+ $currentStore = Mage::app()->getStore()->getId();
15
+
16
+ $websiteId = $this->helper('koan_seg')->getWebsiteId($currentStore);
17
  if (empty($websiteId)) {
18
  $this->_template = null;
19
  }
app/code/community/Koan/Seg/Block/Track.php CHANGED
@@ -13,6 +13,7 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
13
  const PAGE_TYPE_CATEGORY = 2;
14
  const PAGE_TYPE_DEFAULT = 3;
15
  const PAGE_TYPE_CHECKOUT_SUCCESS = 4;
 
16
 
17
  public function getCustomerData()
18
  {
@@ -26,11 +27,12 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
26
 
27
  $result = array('Email' => $email);
28
 
 
29
  $id = $customer->getId();
30
  if (!empty($id)) {
31
  $result['Id'] = $id;
32
  }
33
-
34
  $title = $customer->getPrefix();
35
  if (!empty($title)) {
36
  $result['Title'] = $title;
@@ -60,9 +62,12 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
60
  $result['CountryCode'] = $country;
61
  }
62
 
63
- $gender = $this->_getAttributeText($customer, 'gender');
64
- if (!empty($gender)) {
65
- $result['Gender'] = $gender;
 
 
 
66
  }
67
 
68
  if ($result AND is_array($result) and count($result)) {
@@ -120,6 +125,11 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
120
  return $result;
121
  }
122
 
 
 
 
 
 
123
  return $result;
124
  }
125
 
@@ -203,6 +213,10 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
203
  return $this->_getOrderSuccessEventCode($order);
204
  break;
205
 
 
 
 
 
206
  default:
207
  return array('event' => 'PageView', 'data' => null);
208
  break;
@@ -215,6 +229,24 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
215
  return null;
216
  }
217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  private function _getAddToCartEventCode($itemId)
219
  {
220
  $cartData = Mage::getModel('koan_seg/seg_basket')->prepare($itemId);
@@ -252,7 +284,7 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
252
 
253
  private function _getOrderSuccessEventCode($order)
254
  {
255
- $orderData = Mage::getModel('koan_seg/seg_order')->prepare($order);
256
 
257
  $result = array(
258
  'event' => 'OrderPlaced',
@@ -281,4 +313,9 @@ class Koan_Seg_Block_Track extends Mage_Core_Block_Template
281
  return Mage::helper('koan_seg');
282
  }
283
 
 
 
 
 
 
284
  }
13
  const PAGE_TYPE_CATEGORY = 2;
14
  const PAGE_TYPE_DEFAULT = 3;
15
  const PAGE_TYPE_CHECKOUT_SUCCESS = 4;
16
+ const PAGE_TYPE_CART = 5;
17
 
18
  public function getCustomerData()
19
  {
27
 
28
  $result = array('Email' => $email);
29
 
30
+ /*
31
  $id = $customer->getId();
32
  if (!empty($id)) {
33
  $result['Id'] = $id;
34
  }
35
+ */
36
  $title = $customer->getPrefix();
37
  if (!empty($title)) {
38
  $result['Title'] = $title;
62
  $result['CountryCode'] = $country;
63
  }
64
 
65
+ $gender = $customer->getGender();
66
+ if($gender){
67
+ $genderTxt = $this->_getAttributeText($customer, 'gender');
68
+ if (!empty($genderTxt)) {
69
+ $result['Gender'] = $genderTxt;
70
+ }
71
  }
72
 
73
  if ($result AND is_array($result) and count($result)) {
125
  return $result;
126
  }
127
 
128
+ if ($moduleName == 'checkout' AND $controllerName == 'cart' AND $actionName == 'index') {
129
+ $result['type'] = self::PAGE_TYPE_CART;
130
+ return $result;
131
+ }
132
+
133
  return $result;
134
  }
135
 
213
  return $this->_getOrderSuccessEventCode($order);
214
  break;
215
 
216
+ case self::PAGE_TYPE_CART:
217
+ return $this->_getCartViewEventCode();
218
+ break;
219
+
220
  default:
221
  return array('event' => 'PageView', 'data' => null);
222
  break;
229
  return null;
230
  }
231
 
232
+ private function _getCartViewEventCode()
233
+ {
234
+ $cart = $this->_getCart();
235
+ $quote = $cart->getQuote();
236
+
237
+ if (!$quote) {
238
+ return false;
239
+ }
240
+
241
+ $cartData = Mage::getModel('koan_seg/seg_basket')->prepareBasketView($quote);
242
+ $result = array(
243
+ 'event' => 'AddedToBasket',
244
+ 'data' => json_encode($cartData)
245
+ );
246
+
247
+ return $result;
248
+ }
249
+
250
  private function _getAddToCartEventCode($itemId)
251
  {
252
  $cartData = Mage::getModel('koan_seg/seg_basket')->prepare($itemId);
284
 
285
  private function _getOrderSuccessEventCode($order)
286
  {
287
+ $orderData = Mage::getModel('koan_seg/seg_order')->prepare($order, false);
288
 
289
  $result = array(
290
  'event' => 'OrderPlaced',
313
  return Mage::helper('koan_seg');
314
  }
315
 
316
+ protected function _getCart()
317
+ {
318
+ return Mage::getSingleton('checkout/cart');
319
+ }
320
+
321
  }
app/code/community/Koan/Seg/Helper/Data.php CHANGED
@@ -8,19 +8,43 @@ class Koan_Seg_Helper_Data extends Mage_Core_Helper_Abstract
8
  const SEG_UPDATE_CUSTOMERS_ENDPOINT_URL_PATH = 'koan_seg/endpoint/update_customers';
9
  const SEG_ORDER_PLACED_ENDPOINT_URL_PATH = 'koan_seg/endpoint/order_placed';
10
 
 
 
11
  const SEG_ORDERS_EXPORT_BATCH_SIZE_PATH = 'koan_seg/general/orders_export_batch_size';
12
  const SEG_CUSTOMERS_EXPORT_BATCH_SIZE_PATH = 'koan_seg/general/customers_export_batch_size';
13
 
14
- const SEG_PRODUCT_BRAND_ATTRIBUTE_CODE_PATH = 'koan_seg/general/brand_attr_code';
 
 
15
  const SEG_ROLLBAR_LOG_REQUEST_INFO = 'koan_seg/general/rollbar_report_params';
16
 
17
  const SEG_EXPORT_CRON_ENABLED = 'koan_seg/general/export_cron_enable';
18
 
19
  const SEG_EXPORTER_PHP_MEMORY_LIMIT = 'koan_seg/advanced/php_memory_limit';
 
20
 
21
- public function getExporterPhpMemoryLimit()
22
  {
23
- return Mage::getStoreConfig(self::SEG_EXPORTER_PHP_MEMORY_LIMIT, null);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
 
26
  public function isExportCronEnabled()
@@ -58,11 +82,12 @@ class Koan_Seg_Helper_Data extends Mage_Core_Helper_Abstract
58
  return Mage::getStoreConfig(self::SEG_CUSTOMERS_EXPORT_BATCH_SIZE_PATH);
59
  }
60
 
61
- public function getBrandAttributeCode($storeId = null)
62
  {
63
- return Mage::getStoreConfig(self::SEG_PRODUCT_BRAND_ATTRIBUTE_CODE_PATH, $storeId);
64
  }
65
 
 
66
  public function logRequestInfo($storeId = null)
67
  {
68
  return Mage::getStoreConfigFlag(self::SEG_ROLLBAR_LOG_REQUEST_INFO, $storeId);
@@ -85,7 +110,8 @@ class Koan_Seg_Helper_Data extends Mage_Core_Helper_Abstract
85
  Rollbar::init(array(
86
 
87
  'access_token' => '39591143a2524b08b29a18a653897f95',
88
- 'environment' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB),
 
89
  'root' => Mage::getBaseDir(),
90
  'batched' => 0,
91
 
@@ -93,78 +119,94 @@ class Koan_Seg_Helper_Data extends Mage_Core_Helper_Abstract
93
  }
94
  }
95
 
96
- public function getProductBrands($product, $storeId)
97
  {
98
- $brandAttributeCode = $this->getBrandAttributeCode($storeId);
99
- $brandAttributeType = null;
 
 
 
100
 
101
- if ($brandAttributeCode) {
102
- $brandAttributeType = $this->_getBrandAttributeType($brandAttributeCode);
 
 
 
103
  }
104
 
105
- //Try to determine product brand
106
- if (is_null($brandAttributeType)) {
107
- $brandAttributeType = 'text';
108
  }
109
 
110
- $getBrand = 'get' . $this->_camelize($brandAttributeCode);
111
 
112
- if ($brandAttributeType == 'select') {
113
 
114
- $resultBrand = null;
115
- $brandValue = $product->$getBrand();
116
 
117
- if (!empty($brandValue)) {
118
- $product->setStoreId($storeId)
119
- ->setData(
120
- $brandAttributeCode,
121
- $brandValue
122
- );
123
- $resultBrand = $product->getAttributeText($brandAttributeCode);
124
- }
 
 
 
 
125
 
126
- } else if ($brandAttributeType == 'multiselect') {
127
-
128
- $productBrandIds = null;
129
- $resultBrand = array();
130
-
131
- $brandValueList = $product->$getBrand();
132
- if ($brandValueList) {
133
- $productBrandValsArray = explode(',', $brandValueList);
134
- if ($productBrandValsArray AND is_array($productBrandValsArray) AND count($productBrandValsArray)) {
135
- foreach ($productBrandValsArray as $brandValue) {
136
- if (!empty($brandValue)) {
137
- $product->setStoreId($storeId)
138
- ->setData(
139
- $brandAttributeCode,
140
- $brandValue
141
- );
142
- $resultBrand[] = $product->getAttributeText($brandAttributeCode);
 
 
 
 
 
 
 
 
143
  }
144
  }
 
 
 
145
  }
146
  }
147
-
148
- } else {
149
- $resultBrand = $product->$getBrand();
150
  }
151
 
152
- $brand = $resultBrand ? $resultBrand : null;
153
-
154
- if (!$brand) {
155
- return null;
 
 
156
  }
157
 
158
- if (!is_array($brand)) {
159
- $brand = array($brand);
160
- }
161
 
162
- return $brand;
163
  }
164
 
165
- private function _getBrandAttributeType($brandAttributeCode)
166
  {
167
- $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $brandAttributeCode);
168
  if ($attribute) {
169
  return $attribute->getFrontendInput();
170
  }
@@ -176,4 +218,52 @@ class Koan_Seg_Helper_Data extends Mage_Core_Helper_Abstract
176
  {
177
  return uc_words($name, '');
178
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  }
8
  const SEG_UPDATE_CUSTOMERS_ENDPOINT_URL_PATH = 'koan_seg/endpoint/update_customers';
9
  const SEG_ORDER_PLACED_ENDPOINT_URL_PATH = 'koan_seg/endpoint/order_placed';
10
 
11
+ const SEG_ORDERS_EXPORT_STATUSES = 'koan_seg/general/orders_export_statuses';
12
+
13
  const SEG_ORDERS_EXPORT_BATCH_SIZE_PATH = 'koan_seg/general/orders_export_batch_size';
14
  const SEG_CUSTOMERS_EXPORT_BATCH_SIZE_PATH = 'koan_seg/general/customers_export_batch_size';
15
 
16
+ // const SEG_PRODUCT_BRAND_ATTRIBUTE_CODE_PATH = 'koan_seg/general/brand_attr_code';
17
+ const SEG_PRODUCT_TAG_ATTRIBUTE_CODES_PATH = 'koan_seg/general/tag_attr_codes';
18
+
19
  const SEG_ROLLBAR_LOG_REQUEST_INFO = 'koan_seg/general/rollbar_report_params';
20
 
21
  const SEG_EXPORT_CRON_ENABLED = 'koan_seg/general/export_cron_enable';
22
 
23
  const SEG_EXPORTER_PHP_MEMORY_LIMIT = 'koan_seg/advanced/php_memory_limit';
24
+ const SEG_EXPORTER_REQUEST_TIMEOUT = 'koan_seg/advanced/request_timeout';
25
 
26
+ public function getOrdersExportStatuses($storeId = null)
27
  {
28
+ $statuses = Mage::getStoreConfig(self::SEG_ORDERS_EXPORT_STATUSES, $storeId);
29
+ if (empty($statuses)) {
30
+ return null;
31
+ }
32
+ $result = array_map('trim', explode(',', $statuses));
33
+ return $result;
34
+ }
35
+
36
+ public function getRequestTimeout($storeId = null)
37
+ {
38
+ $timeOut = Mage::getStoreConfig(self::SEG_EXPORTER_PHP_MEMORY_LIMIT, $storeId);
39
+ if (!$timeOut) {
40
+ $timeOut = 60;
41
+ }
42
+ return $timeOut;
43
+ }
44
+
45
+ public function getExporterPhpMemoryLimit($storeId = null)
46
+ {
47
+ return Mage::getStoreConfig(self::SEG_EXPORTER_PHP_MEMORY_LIMIT, $storeId);
48
  }
49
 
50
  public function isExportCronEnabled()
82
  return Mage::getStoreConfig(self::SEG_CUSTOMERS_EXPORT_BATCH_SIZE_PATH);
83
  }
84
 
85
+ public function getTagAttributeCodes($storeId = null)
86
  {
87
+ return Mage::getStoreConfig(self::SEG_PRODUCT_TAG_ATTRIBUTE_CODES_PATH, $storeId);
88
  }
89
 
90
+
91
  public function logRequestInfo($storeId = null)
92
  {
93
  return Mage::getStoreConfigFlag(self::SEG_ROLLBAR_LOG_REQUEST_INFO, $storeId);
110
  Rollbar::init(array(
111
 
112
  'access_token' => '39591143a2524b08b29a18a653897f95',
113
+ //'environment' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB),
114
+ 'environment' => 'production',
115
  'root' => Mage::getBaseDir(),
116
  'batched' => 0,
117
 
119
  }
120
  }
121
 
122
+ public function getProductTags($product, $storeId)
123
  {
124
+ $tagAttributeCodes = $this->getTagAttributeCodes($storeId);
125
+ $tagAttributeType = null;
126
+
127
+ $cache = Mage::app()->getCache();
128
+ $cacheKey = md5($tagAttributeCodes . $product->getId() . $storeId);
129
 
130
+ if (Mage::app()->useCache('COLLECTION_DATA')) {
131
+ $result = $cache->load($cacheKey);
132
+ if ($result) {
133
+ return unserialize($result);
134
+ }
135
  }
136
 
137
+ if ($tagAttributeCodes) {
138
+ $tagAttributeCodes = array_map('trim', explode(',', $tagAttributeCodes));
 
139
  }
140
 
141
+ $tags = array();
142
 
143
+ if ($tagAttributeCodes AND is_array($tagAttributeCodes) AND count($tagAttributeCodes)) {
144
 
145
+ foreach ($tagAttributeCodes as $attributeCode) {
 
146
 
147
+ $attrType = $this->_getAttributeTypeByCode($attributeCode);
148
+ //Try to determine product brand
149
+ if (is_null($attrType)) {
150
+ $attrType = 'text';
151
+ }
152
+
153
+ $getAttribute = 'get' . $this->_camelize($attributeCode);
154
+
155
+ if ($attrType == 'select') {
156
+
157
+ $resultBrand = null;
158
+ $attrValue = $product->$getAttribute();
159
 
160
+ if (!empty($attrValue)) {
161
+ $product->setStoreId($storeId)
162
+ ->setData(
163
+ $attributeCode,
164
+ $attrValue
165
+ );
166
+ $tags[] = $product->getAttributeText($attributeCode);
167
+ }
168
+ } else if ($attrType == 'multiselect') {
169
+
170
+ $productAttrIds = null;
171
+ $attrValueList = $product->$getAttribute();
172
+ if ($attrValueList) {
173
+ $productAttrValsArray = explode(',', $attrValueList);
174
+ if ($productAttrValsArray AND is_array($productAttrValsArray) AND count($productAttrValsArray)) {
175
+ foreach ($productAttrValsArray as $attrValue) {
176
+ if (!empty($attrValue)) {
177
+ $product->setStoreId($storeId)
178
+ ->setData(
179
+ $attributeCode,
180
+ $attrValue
181
+ );
182
+ $tags[] = $product->getAttributeText($attributeCode);
183
+ }
184
+ }
185
  }
186
  }
187
+
188
+ } else {
189
+ $tags[] = $product->$getAttribute();
190
  }
191
  }
 
 
 
192
  }
193
 
194
+ if ($tags AND is_array($tags) AND count($tags)) {
195
+ foreach ($tags as $key => $tag) {
196
+ if (is_null($tags[$key])) {
197
+ unset($tags[$key]);
198
+ }
199
+ }
200
  }
201
 
202
+ $cache->save(serialize($tags), $cacheKey, array('COLLECTION_DATA'), 86400);
 
 
203
 
204
+ return $tags;
205
  }
206
 
207
+ private function _getAttributeTypeByCode($code)
208
  {
209
+ $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $code);
210
  if ($attribute) {
211
  return $attribute->getFrontendInput();
212
  }
218
  {
219
  return uc_words($name, '');
220
  }
221
+
222
+ public function getAllProductCategories($product)
223
+ {
224
+ //$product->load($product->getId());
225
+
226
+ $cache = Mage::app()->getCache();
227
+
228
+ $result = null;
229
+
230
+ $catIds = $product->getCategoryIds();
231
+
232
+ $cacheKey = md5('catresult-' . $product->getId() . $catIds);
233
+
234
+ if (Mage::app()->useCache('COLLECTION_DATA')) {
235
+ $result = $cache->load($cacheKey);
236
+ if ($result) {
237
+ return unserialize($result);
238
+ }
239
+ }
240
+
241
+ if ($catIds AND is_array($catIds) AND count($catIds)) {
242
+
243
+ $catsCollection = Mage::getModel('catalog/category')->getCollection();
244
+ $catsCollection->addIsActiveFilter();
245
+
246
+ $catsCollection->addNameToResult();
247
+ $catsCollection->addFieldToFilter('entity_id', array('in' => $catIds));
248
+
249
+ $result = array();
250
+
251
+ foreach ($catsCollection as $cat) {
252
+ $parentCategories = $cat->getParentCategories();
253
+ foreach ($parentCategories as $parent) {
254
+ if ($parent->getLevel() == 1) {
255
+ continue;
256
+ }
257
+ $result[$parent->getId()] = $parent->getName();
258
+ }
259
+
260
+ $result[$cat->getId()] = $cat->getName();
261
+ }
262
+
263
+ $cache->save(serialize($result), $cacheKey, array('COLLECTION_DATA'), 86400);
264
+ }
265
+
266
+ return $result;
267
+
268
+ }
269
  }
app/code/community/Koan/Seg/Model/Batch/Log.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Batch_Log extends Mage_Core_Model_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ parent::_construct();
8
+ $this->_init('koan_seg/batch_log');
9
+ }
10
+ }
app/code/community/Koan/Seg/Model/Batch/Status.php CHANGED
@@ -8,7 +8,7 @@ class Koan_Seg_Model_Batch_Status extends Mage_Core_Model_Abstract
8
  $this->_init('koan_seg/batch_status');
9
  }
10
 
11
- public function createNew($entityType = null, $filter = null)
12
  {
13
  $data = array(
14
  'entity_type' => $entityType,
@@ -18,7 +18,8 @@ class Koan_Seg_Model_Batch_Status extends Mage_Core_Model_Abstract
18
  'num_rows_processed' => 0,
19
  'current_status' => 0,
20
  'comment' => 'Waiting for start ...',
21
- 'num_retried' => 0
 
22
  );
23
 
24
  if ($filter) {
@@ -85,11 +86,30 @@ class Koan_Seg_Model_Batch_Status extends Mage_Core_Model_Abstract
85
  $data = array(
86
  'num_retried' => $numRetried,
87
  'comment' => $message,
 
88
  );
89
 
90
- if ($numRetried >= 3) {
91
- $data['current_status'] = Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR;
 
 
 
 
 
 
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  $this->addData(
95
  $data
8
  $this->_init('koan_seg/batch_status');
9
  }
10
 
11
+ public function createNew($websiteId, $entityType = null, $filter = null)
12
  {
13
  $data = array(
14
  'entity_type' => $entityType,
18
  'num_rows_processed' => 0,
19
  'current_status' => 0,
20
  'comment' => 'Waiting for start ...',
21
+ 'num_retried' => 0,
22
+ 'website_id' => $websiteId
23
  );
24
 
25
  if ($filter) {
86
  $data = array(
87
  'num_retried' => $numRetried,
88
  'comment' => $message,
89
+ 'current_status' => Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR,
90
  );
91
 
92
+ $this->addData(
93
+ $data
94
+ );
95
+
96
+ try {
97
+ $this->save();
98
+ } Catch (Exception $e) {
99
+ throw $e;
100
  }
101
+ }
102
+
103
+ public function setBatchRetryError($message)
104
+ {
105
+ $numRetried = is_null($this->getNumRetried()) ? 0 : $this->getNumRetried();
106
+ $numRetried++;
107
+
108
+ $data = array(
109
+ 'num_retried' => $numRetried,
110
+ 'comment' => $message,
111
+ 'current_status' => Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_NEED_RETRY,
112
+ );
113
 
114
  $this->addData(
115
  $data
app/code/community/Koan/Seg/Model/Config/Source/Websites.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Config_Source_Websites
4
+ {
5
+ public function toOptionArray()
6
+ {
7
+ $websites = Mage::app()->getWebsites();
8
+ $result = array();
9
+
10
+ foreach ($websites as $website) {
11
+ $value = Mage::getConfig()->getNode(sprintf('websites/%s/koan_seg/general/seg_website_id', $website->getCode()));
12
+ if ($value and count($value) > 0) {
13
+ $result[] = array('value' => $website->getId(), 'label' => $website->getName() . ' - ' . $value[0]);
14
+ }
15
+ }
16
+
17
+ return $result;
18
+
19
+ }
20
+
21
+ }
app/code/community/Koan/Seg/Model/Guid/Validator.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Guid_Validator extends Mage_Core_Model_Config_Data
4
+ {
5
+ protected function _beforeSave()
6
+ {
7
+ $value = $this->getValue();
8
+
9
+ if ($value AND (strlen($value) != 36)) {
10
+ Mage::throwException('Proper Website Id Length should be 32 characters!');
11
+ }
12
+
13
+ return $this;
14
+ }
15
+ }
app/code/community/Koan/Seg/Model/Observer.php CHANGED
@@ -48,7 +48,7 @@ class Koan_Seg_Model_Observer
48
  if ($quoteItem->getParentItemId()) {
49
  Mage::getSingleton('customer/session')->setItemAddedToCart($quoteItem->getParentItemId());
50
  $quoteItem->unsAddedToCartFlag();
51
- } else if ($quoteItem->hasId()) {
52
  Mage::getSingleton('customer/session')->setItemAddedToCart($quoteItem->getId());
53
  $quoteItem->unsAddedToCartFlag();
54
  }
@@ -70,9 +70,11 @@ class Koan_Seg_Model_Observer
70
  return $observer;
71
  }
72
 
 
 
73
  try {
74
  $orderData = Mage::getModel('koan_seg/seg_order')->prepare($order);
75
- Mage::getModel('koan_seg/seg_client')->exportNewOrder($orderData);
76
  } Catch (Exception $e) {
77
  Mage::getSingleton('koan_seg/exception_handler')->handle('Magento: error in orderPlaceAfter observer - exportNewOrder', $e);
78
  }
48
  if ($quoteItem->getParentItemId()) {
49
  Mage::getSingleton('customer/session')->setItemAddedToCart($quoteItem->getParentItemId());
50
  $quoteItem->unsAddedToCartFlag();
51
+ } else if ($quoteItem->getId()) {
52
  Mage::getSingleton('customer/session')->setItemAddedToCart($quoteItem->getId());
53
  $quoteItem->unsAddedToCartFlag();
54
  }
70
  return $observer;
71
  }
72
 
73
+ $storeId = is_null($order->getStoreId()) ? 0 : $order->getStoreId();
74
+
75
  try {
76
  $orderData = Mage::getModel('koan_seg/seg_order')->prepare($order);
77
+ Mage::getModel('koan_seg/seg_client')->exportNewOrder($orderData, $storeId);
78
  } Catch (Exception $e) {
79
  Mage::getSingleton('koan_seg/exception_handler')->handle('Magento: error in orderPlaceAfter observer - exportNewOrder', $e);
80
  }
app/code/community/Koan/Seg/Model/Resource/Batch/Log.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Resource_Batch_Log extends Mage_Core_Model_Resource_Db_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ $this->_init('koan_seg/batch_log', 'id');
8
+ }
9
+ }
app/code/community/Koan/Seg/Model/Resource/Batch/Log/Collection.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Resource_Batch_Log_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ parent::_construct();
8
+ $this->_init('koan_seg/batch_log');
9
+ }
10
+ }
app/code/community/Koan/Seg/Model/Resource/Log/Status.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Resource_Batch_Status extends Mage_Core_Model_Resource_Db_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ $this->_init('koan_seg/batch_status', 'id');
8
+ }
9
+ }
app/code/community/Koan/Seg/Model/Resource/Log/Status/Collection.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_Resource_Batch_Status_Collection extends Mage_Core_Model_Resource_Db_Collection_Abstract
4
+ {
5
+ public function _construct()
6
+ {
7
+ parent::_construct();
8
+ $this->_init('koan_seg/batch_status');
9
+ }
10
+ }
app/code/community/Koan/Seg/Model/Seg/Basket.php CHANGED
@@ -62,6 +62,54 @@ class Koan_Seg_Model_Seg_Basket extends Varien_Object
62
  return $this->toArray($resultAttributes);
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  private function _prepareQuoteLines($quote, $addedItemId)
66
  {
67
  $quoteItems = $quote->getAllVisibleItems();
62
  return $this->toArray($resultAttributes);
63
  }
64
 
65
+ public function prepareBasketView($quote)
66
+ {
67
+ if (!$quote) {
68
+ Mage::throwException('Quote is not valid!');
69
+ }
70
+
71
+ if (!$quoteId = $quote->getId()) {
72
+ Mage::throwException('Missing Quote Id');
73
+ }
74
+
75
+ $revenue = is_null($quote->getBaseGrandTotal()) ? 0 : $quote->getBaseGrandTotal();
76
+
77
+ $resultAttributes = array(
78
+ 'Discount',
79
+ 'Id',
80
+ 'OrderLines',
81
+ //'_p',
82
+ 'Revenue'
83
+ );
84
+
85
+ $shippingAddress = $quote->getShippingAddress();
86
+
87
+ $shippingMethod = $shippingAddress->getShippingDescription();
88
+ if (!empty($shippingMethod)) {
89
+ $this->setData('DeliveryMethod', $shippingMethod);
90
+ $resultAttributes[] = 'DeliveryMethod';
91
+ }
92
+
93
+ $deliveryRevenue = $shippingAddress->getBaseShippingInclTax();
94
+ if (!is_null($deliveryRevenue)) {
95
+ $this->setData('DeliveryRevenue', number_format($deliveryRevenue, 2, '.', ''));
96
+ $resultAttributes[] = 'DeliveryRevenue';
97
+ }
98
+
99
+ $discountAmount = $shippingAddress->getBaseDiscountAmount();
100
+ if (!is_null($discountAmount)) {
101
+ $this->setData('Discount', number_format($discountAmount, 2, '.', ''));
102
+ $resultAttributes[] = 'Discount';
103
+ }
104
+
105
+ $this->setData('Id', $quoteId);
106
+ $this->setData('OrderLines', $this->_prepareQuoteLines($quote, 0));
107
+
108
+ $this->setData('Revenue', number_format($revenue, 2, '.', ''));
109
+
110
+ return $this->toArray($resultAttributes);
111
+ }
112
+
113
  private function _prepareQuoteLines($quote, $addedItemId)
114
  {
115
  $quoteItems = $quote->getAllVisibleItems();
app/code/community/Koan/Seg/Model/Seg/Client.php CHANGED
@@ -4,8 +4,6 @@ Mage::helper('koan_seg')->includeRollBar();
4
 
5
  class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
6
  {
7
- const REQUEST_TIMEOUT = 30;
8
-
9
  public function __construct()
10
  {
11
  //$this->_getHelper()->initRollbar();
@@ -14,7 +12,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
14
  parent::__construct();
15
  }
16
 
17
- public function exportCustomers($customers)
18
  {
19
  if (!$customers) {
20
  Mage::throwException($this->__('Customers data does not exists!'));
@@ -26,7 +24,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
26
 
27
  $params = json_encode($customers);
28
 
29
- $url = $this->_getExportCustomerUrl();
30
 
31
  $this->_init();
32
  $this->setUri($url);
@@ -52,7 +50,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
52
  return $this;
53
  }
54
 
55
- public function exportHistoryOrders($orders)
56
  {
57
  if (!$orders) {
58
  Mage::throwException($this->__('Order data does not exists!'));
@@ -64,7 +62,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
64
 
65
  $params = json_encode($orders);
66
 
67
- $url = $this->_getExportOrderHistoryUrl();
68
 
69
  $this->_init();
70
  $this->setUri($url);
@@ -76,7 +74,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
76
  $batchSize = 20;
77
  $total = count($orders);
78
 
79
- $numBatches = floor(floatval($total) / floatval($batchSize)) + (floatval($total) % floatval($batchSize));
80
  $batchCounter = 0;
81
 
82
  $batch = array();
@@ -85,24 +83,12 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
85
  foreach ($orders as $order) {
86
  $counter++;
87
 
88
- if ($counter >= $total) {
 
89
  $batchCounter++;
90
  $logData = json_encode($batch);
91
  Mage::getSingleton('koan_seg/logger')->log(
92
  'Magento: posting history orders to Seg', 'info', array('orders' => $logData, 'endpoint' => $url, 'batch' => $batchCounter, 'batches' => $numBatches));
93
-
94
- break;
95
- }
96
-
97
- if (count($batch) < $batchSize) {
98
- $batch[] = $order;
99
- } else {
100
- $batchCounter++;
101
- $logData = json_encode($batch);
102
-
103
- Mage::getSingleton('koan_seg/logger')->log(
104
- 'Magento: posting history orders to Seg', 'info', array('orders' => $logData, 'endpoint' => $url, 'batch' => $batchCounter, 'batches' => $numBatches));
105
-
106
  $batch = array();
107
  }
108
 
@@ -117,15 +103,16 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
117
  }
118
 
119
  try {
120
- $this->__handleResponse($response, 'posting history orders to Seg');
121
  } Catch (Exception $e) {
122
  Mage::throwException('[exportHistoryOrders]::__handleResponse: ' . $e->getMessage());
 
123
  }
124
 
125
  return $this;
126
  }
127
 
128
- public function exportNewOrder($orderData)
129
  {
130
  if (!$orderData) {
131
  Mage::throwException($this->__('Order data does not exists!'));
@@ -137,7 +124,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
137
 
138
  $params = json_encode($orderData);
139
 
140
- $url = $this->_getOrderPlacedUrl();
141
 
142
  $this->_init();
143
  $this->setUri($url);
@@ -178,6 +165,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
178
  $code = $response->getStatus();
179
  $message = $response->getMessage();
180
  Mage::getSingleton('koan_seg/exception_handler')->handleHttpResponseError(sprintf('Magento: error in \'%s\' HTTP request: %s', $msg, $message), $code, $message);
 
181
  }
182
 
183
  return false;
@@ -194,19 +182,19 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
194
  return $this;
195
  }
196
 
197
- private function _getExportCustomerUrl()
198
  {
199
- return sprintf($this->_getHelper()->getUpdateCustomersUrl(), $this->_getHelper()->getWebsiteId());
200
  }
201
 
202
- private function _getExportOrderHistoryUrl()
203
  {
204
- return sprintf($this->_getHelper()->getOrderHistoryUrl(), $this->_getHelper()->getWebsiteId());
205
  }
206
 
207
  private function _getOrderPlacedUrl()
208
  {
209
- return sprintf($this->_getHelper()->getOrderPlacedUrl(), $this->_getHelper()->getWebsiteId());
210
  }
211
 
212
  private function _getHttpHeaders()
@@ -224,7 +212,7 @@ class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
224
 
225
  private function _getTimeout()
226
  {
227
- return self::REQUEST_TIMEOUT;
228
  }
229
 
230
  private function _getHelper()
4
 
5
  class Koan_Seg_Model_Seg_Client extends Varien_Http_Client
6
  {
 
 
7
  public function __construct()
8
  {
9
  //$this->_getHelper()->initRollbar();
12
  parent::__construct();
13
  }
14
 
15
+ public function exportCustomers($customers, $storeId = null)
16
  {
17
  if (!$customers) {
18
  Mage::throwException($this->__('Customers data does not exists!'));
24
 
25
  $params = json_encode($customers);
26
 
27
+ $url = $this->_getExportCustomerUrl($storeId);
28
 
29
  $this->_init();
30
  $this->setUri($url);
50
  return $this;
51
  }
52
 
53
+ public function exportHistoryOrders($orders, $storeId = null)
54
  {
55
  if (!$orders) {
56
  Mage::throwException($this->__('Order data does not exists!'));
62
 
63
  $params = json_encode($orders);
64
 
65
+ $url = $this->_getExportOrderHistoryUrl($storeId);
66
 
67
  $this->_init();
68
  $this->setUri($url);
74
  $batchSize = 20;
75
  $total = count($orders);
76
 
77
+ $numBatches = ceil(floatval($total) / floatval($batchSize));
78
  $batchCounter = 0;
79
 
80
  $batch = array();
83
  foreach ($orders as $order) {
84
  $counter++;
85
 
86
+ $batch[] = $order;
87
+ if ((count($batch) >= $batchSize) OR ($counter == $total)) {
88
  $batchCounter++;
89
  $logData = json_encode($batch);
90
  Mage::getSingleton('koan_seg/logger')->log(
91
  'Magento: posting history orders to Seg', 'info', array('orders' => $logData, 'endpoint' => $url, 'batch' => $batchCounter, 'batches' => $numBatches));
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  $batch = array();
93
  }
94
 
103
  }
104
 
105
  try {
106
+ $result = $this->__handleResponse($response, 'posting history orders to Seg');
107
  } Catch (Exception $e) {
108
  Mage::throwException('[exportHistoryOrders]::__handleResponse: ' . $e->getMessage());
109
+
110
  }
111
 
112
  return $this;
113
  }
114
 
115
+ public function exportNewOrder($orderData, $storeId = null)
116
  {
117
  if (!$orderData) {
118
  Mage::throwException($this->__('Order data does not exists!'));
124
 
125
  $params = json_encode($orderData);
126
 
127
+ $url = $this->_getOrderPlacedUrl($storeId);
128
 
129
  $this->_init();
130
  $this->setUri($url);
165
  $code = $response->getStatus();
166
  $message = $response->getMessage();
167
  Mage::getSingleton('koan_seg/exception_handler')->handleHttpResponseError(sprintf('Magento: error in \'%s\' HTTP request: %s', $msg, $message), $code, $message);
168
+ Mage::throwException($response->getStatus() . ' - ' . $response->getMessage());
169
  }
170
 
171
  return false;
182
  return $this;
183
  }
184
 
185
+ private function _getExportCustomerUrl($storeId)
186
  {
187
+ return sprintf($this->_getHelper()->getUpdateCustomersUrl(), $this->_getHelper()->getWebsiteId($storeId));
188
  }
189
 
190
+ private function _getExportOrderHistoryUrl($storeId)
191
  {
192
+ return sprintf($this->_getHelper()->getOrderHistoryUrl(), $this->_getHelper()->getWebsiteId($storeId));
193
  }
194
 
195
  private function _getOrderPlacedUrl()
196
  {
197
+ return sprintf($this->_getHelper()->getOrderPlacedUrl(), $this->_getHelper()->getWebsiteId($storeId));
198
  }
199
 
200
  private function _getHttpHeaders()
212
 
213
  private function _getTimeout()
214
  {
215
+ return $this->_getHelper()->getRequestTimeout();
216
  }
217
 
218
  private function _getHelper()
app/code/community/Koan/Seg/Model/Seg/Exporter.php CHANGED
@@ -9,6 +9,8 @@ class Koan_Seg_Model_Seg_Exporter
9
  const BATCH_STATUS_COMPLETE = 5;
10
  const BATCH_STATUS_ERROR = 6;
11
 
 
 
12
  const BATCH_ENTITY_TYPE_HISTORY_ORDERS = 'history_orders';
13
  const BATCH_ENTITY_TYPE_CUSTOMERS = 'customers';
14
 
@@ -25,7 +27,7 @@ class Koan_Seg_Model_Seg_Exporter
25
  /**************************************** CUSTOMERS ******************************************/
26
 
27
  //Prepare new customers batch to export
28
- public function generateCustomersExportBatch()
29
  {
30
  if (self::$_exportCustomersGenerateCron == true) {
31
  return $this;
@@ -34,7 +36,7 @@ class Koan_Seg_Model_Seg_Exporter
34
  $this->_getHelper()->initRollbar();
35
 
36
  try {
37
- $this->_exportCustomers(true);
38
  } Catch (Exception $e) {
39
  Mage::getSingleton('koan_seg/exception_handler')->handle('Magento: error in generateCustomersExportBatch', $e);
40
  }
@@ -69,10 +71,10 @@ class Koan_Seg_Model_Seg_Exporter
69
  return $this;
70
  }
71
 
72
- private function _exportCustomers($createNew = false)
73
  {
74
  if ($createNew == true) {
75
- Mage::getModel('koan_seg/batch_status')->createNew(self::BATCH_ENTITY_TYPE_CUSTOMERS);
76
  return $this;
77
  }
78
 
@@ -85,21 +87,37 @@ class Koan_Seg_Model_Seg_Exporter
85
  foreach ($batchRows as $batch) {
86
 
87
  try {
 
 
 
 
88
  $currentStatus = $batch->getCurrentStatus();
 
89
 
90
  switch ($currentStatus) {
91
  case self::BATCH_STATUS_NOT_STARTED:
92
- $totalItemsCount = $this->_getCustomersCollectionSize();
93
  $batch->setStartingStatus($totalItemsCount, self::BATCH_STATUS_STARTING);
94
  case self::BATCH_STATUS_STARTING:
95
  $batch->setProcessingStatus(self::BATCH_STATUS_PROCESSING_ROWS);
96
  case self::BATCH_STATUS_PROCESSING_ROWS:
97
- $this->_processExportCustomers($batch);
98
- $batch->setCompleteStatus(self::BATCH_STATUS_COMPLETE);
 
 
 
 
 
 
 
 
99
  }
100
 
101
  } Catch (Exception $e) {
102
- $batch->setBatchError($e->getMessage());
 
 
 
103
  throw $e;
104
  }
105
 
@@ -108,20 +126,23 @@ class Koan_Seg_Model_Seg_Exporter
108
  return $this;
109
  }
110
 
111
- public function _getCustomersCollectionSize()
112
  {
113
- $collection = $this->_getCustomersCollection();
114
  return $collection->getSize();
115
  }
116
 
117
- public function _getCustomersCollection()
118
  {
119
  if (!$this->_customersCollection) {
120
  $collection = Mage::getResourceModel('customer/customer_collection')
121
  ->addAttributeToSelect('*')
122
  ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left')
123
  ->joinAttribute('shipping_country_id', 'customer_address/country_id', 'default_shipping', null, 'left');
124
- //->load();
 
 
 
125
 
126
  $this->_customersCollection = $collection;
127
  }
@@ -131,33 +152,66 @@ class Koan_Seg_Model_Seg_Exporter
131
 
132
  private function _processExportCustomers($batch)
133
  {
 
 
134
  $numProcTotal = is_null($batch->getNumRowsProcessed()) ? 0 : intval($batch->getNumRowsProcessed());
135
  $totalRows = is_null($batch->getTotalRowCount()) ? 0 : intval($batch->getTotalRowCount());
136
 
 
 
137
  if ($numProcTotal < $totalRows) {
138
 
139
  $break = false;
140
 
141
  do {
142
 
143
- $collection = clone $this->_getCustomersCollection();
144
  $collection->setOrder('entity_id', 'ASC');
145
  $collection->getSelect()->limit($this->_getExportCustomersPageSize(), $numProcTotal);
146
  $collection->load();
147
 
148
  $numProcessed = 0;
149
 
150
- $customers = array();
151
- foreach ($collection as $customer) {
152
 
153
- $customers[] = Mage::getModel('koan_seg/seg_customer')->prepare($customer);
154
- $numProcessed++;
155
- }
156
 
157
- Mage::getModel('koan_seg/seg_client')->exportCustomers($customers);
 
 
158
 
159
- unset($customers);
160
- $customers = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
 
162
  $numProcTotal += $numProcessed;
163
  $batch->updateNumRowsProcessed(null, $numProcessed);
@@ -172,6 +226,72 @@ class Koan_Seg_Model_Seg_Exporter
172
 
173
  }
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  }
176
 
177
  private function _getExportCustomersPageSize()
@@ -184,7 +304,7 @@ class Koan_Seg_Model_Seg_Exporter
184
  /**************************************** ORDERS ******************************************/
185
 
186
  //Prepare new history orders batch to export
187
- public function generateHistoryOrdersExportBatch($orderDateFilter = null)
188
  {
189
  if (self::$_exportHistoryOrdersGenerateCron == true) {
190
  return $this;
@@ -193,7 +313,7 @@ class Koan_Seg_Model_Seg_Exporter
193
  $this->_getHelper()->initRollbar();
194
 
195
  try {
196
- $this->_exportHistoryOrders(true, $orderDateFilter);
197
  } Catch (Exception $e) {
198
  Mage::getSingleton('koan_seg/exception_handler')->handle('Magento: error in generateHistoryOrdersExportBatch', $e);
199
  }
@@ -228,10 +348,10 @@ class Koan_Seg_Model_Seg_Exporter
228
  return $this;
229
  }
230
 
231
- private function _exportHistoryOrders($createNew = false, $orderDateFilter = null)
232
  {
233
  if ($createNew == true) {
234
- Mage::getModel('koan_seg/batch_status')->createNew(self::BATCH_ENTITY_TYPE_HISTORY_ORDERS, $orderDateFilter);
235
  return $this;
236
  }
237
 
@@ -242,6 +362,9 @@ class Koan_Seg_Model_Seg_Exporter
242
  }
243
 
244
  foreach ($batchRows as $batch) {
 
 
 
245
  try {
246
  $currentStatus = $batch->getCurrentStatus();
247
 
@@ -252,8 +375,16 @@ class Koan_Seg_Model_Seg_Exporter
252
  case self::BATCH_STATUS_STARTING:
253
  $batch->setProcessingStatus(self::BATCH_STATUS_PROCESSING_ROWS);
254
  case self::BATCH_STATUS_PROCESSING_ROWS:
255
- $this->_processExportHistoryOrders($batch);
256
- $batch->setCompleteStatus(self::BATCH_STATUS_COMPLETE);
 
 
 
 
 
 
 
 
257
  }
258
 
259
  } Catch (Exception $e) {
@@ -266,8 +397,74 @@ class Koan_Seg_Model_Seg_Exporter
266
  return $this;
267
  }
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  private function _processExportHistoryOrders($batch)
270
  {
 
 
271
  $numProcTotal = is_null($batch->getNumRowsProcessed()) ? 0 : intval($batch->getNumRowsProcessed());
272
  $totalRows = is_null($batch->getTotalRowCount()) ? 0 : intval($batch->getTotalRowCount());
273
 
@@ -284,18 +481,47 @@ class Koan_Seg_Model_Seg_Exporter
284
 
285
  $numProcessed = 0;
286
 
287
- $orders = array();
288
- foreach ($collection as $order) {
289
 
290
- //TODO: Handle collection export
291
- $orders[] = Mage::getModel('koan_seg/seg_order')->prepare($order);
292
- $numProcessed++;
293
- }
294
 
295
- Mage::getModel('koan_seg/seg_client')->exportHistoryOrders($orders);
 
 
 
296
 
297
- unset($orders);
298
- $orders = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
 
300
  $numProcTotal += $numProcessed;
301
  $batch->updateNumRowsProcessed(null, $numProcessed);
@@ -309,6 +535,7 @@ class Koan_Seg_Model_Seg_Exporter
309
 
310
  }
311
 
 
312
  }
313
 
314
  private function _getExportHistoryPageSize()
@@ -341,7 +568,8 @@ class Koan_Seg_Model_Seg_Exporter
341
  $allowedStages = array(
342
  self::BATCH_STATUS_NOT_STARTED,
343
  self::BATCH_STATUS_STARTING,
344
- self::BATCH_STATUS_PROCESSING_ROWS
 
345
  );
346
 
347
  $collection = Mage::getResourceModel('koan_seg/batch_status_collection');
@@ -359,9 +587,24 @@ class Koan_Seg_Model_Seg_Exporter
359
 
360
  public function _getHistoryOrdersCollection($batch = null)
361
  {
 
 
 
 
 
 
362
  if (!$this->_historyOrdersCollection) {
363
  $collection = Mage::getResourceModel('sales/order_collection');
364
- $collection->addFieldToFilter('state', 'complete');
 
 
 
 
 
 
 
 
 
365
 
366
  if ($batch AND $filter = $batch->getFilter()) {
367
  $collection->addFieldToFilter('created_at', array('from' => $filter));
9
  const BATCH_STATUS_COMPLETE = 5;
10
  const BATCH_STATUS_ERROR = 6;
11
 
12
+ const BATCH_STATUS_NEED_RETRY = 7;
13
+
14
  const BATCH_ENTITY_TYPE_HISTORY_ORDERS = 'history_orders';
15
  const BATCH_ENTITY_TYPE_CUSTOMERS = 'customers';
16
 
27
  /**************************************** CUSTOMERS ******************************************/
28
 
29
  //Prepare new customers batch to export
30
+ public function generateCustomersExportBatch($websiteId)
31
  {
32
  if (self::$_exportCustomersGenerateCron == true) {
33
  return $this;
36
  $this->_getHelper()->initRollbar();
37
 
38
  try {
39
+ $this->_exportCustomers(true, $websiteId);
40
  } Catch (Exception $e) {
41
  Mage::getSingleton('koan_seg/exception_handler')->handle('Magento: error in generateCustomersExportBatch', $e);
42
  }
71
  return $this;
72
  }
73
 
74
+ private function _exportCustomers($createNew = false, $websiteId = null)
75
  {
76
  if ($createNew == true) {
77
+ Mage::getModel('koan_seg/batch_status')->createNew($websiteId, self::BATCH_ENTITY_TYPE_CUSTOMERS);
78
  return $this;
79
  }
80
 
87
  foreach ($batchRows as $batch) {
88
 
89
  try {
90
+
91
+ //Reset collection:
92
+ $this->_customersCollection = null;
93
+
94
  $currentStatus = $batch->getCurrentStatus();
95
+ $websiteId = $batch->getWebsiteId();
96
 
97
  switch ($currentStatus) {
98
  case self::BATCH_STATUS_NOT_STARTED:
99
+ $totalItemsCount = $this->_getCustomersCollectionSize($websiteId);
100
  $batch->setStartingStatus($totalItemsCount, self::BATCH_STATUS_STARTING);
101
  case self::BATCH_STATUS_STARTING:
102
  $batch->setProcessingStatus(self::BATCH_STATUS_PROCESSING_ROWS);
103
  case self::BATCH_STATUS_PROCESSING_ROWS:
104
+ $errors = $this->_processExportCustomers($batch);
105
+ if (count($errors)) {
106
+ $batch->setBatchRetryError('Some errors occured during the batch export. Pending retry.');
107
+ } else {
108
+ $batch->setCompleteStatus(self::BATCH_STATUS_COMPLETE);
109
+ }
110
+ break;
111
+ case self::BATCH_STATUS_NEED_RETRY:
112
+ $this->_retryExportCustomers($batch);
113
+ break;
114
  }
115
 
116
  } Catch (Exception $e) {
117
+ $msg = $batch->setBatchError($e->getMessage());
118
+ if ($msg) {
119
+ $e->setMessage($msg);
120
+ }
121
  throw $e;
122
  }
123
 
126
  return $this;
127
  }
128
 
129
+ public function _getCustomersCollectionSize($websiteId)
130
  {
131
+ $collection = $this->_getCustomersCollection($websiteId);
132
  return $collection->getSize();
133
  }
134
 
135
+ public function _getCustomersCollection($websiteId)
136
  {
137
  if (!$this->_customersCollection) {
138
  $collection = Mage::getResourceModel('customer/customer_collection')
139
  ->addAttributeToSelect('*')
140
  ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left')
141
  ->joinAttribute('shipping_country_id', 'customer_address/country_id', 'default_shipping', null, 'left');
142
+
143
+ if (Mage::getModel('customer/config_share')->isWebsiteScope()) {
144
+ $collection->addFieldToFilter('website_id', $websiteId);
145
+ }
146
 
147
  $this->_customersCollection = $collection;
148
  }
152
 
153
  private function _processExportCustomers($batch)
154
  {
155
+ $errors = array();
156
+
157
  $numProcTotal = is_null($batch->getNumRowsProcessed()) ? 0 : intval($batch->getNumRowsProcessed());
158
  $totalRows = is_null($batch->getTotalRowCount()) ? 0 : intval($batch->getTotalRowCount());
159
 
160
+ $websiteId = $batch->getWebsiteId();
161
+
162
  if ($numProcTotal < $totalRows) {
163
 
164
  $break = false;
165
 
166
  do {
167
 
168
+ $collection = clone $this->_getCustomersCollection($websiteId);
169
  $collection->setOrder('entity_id', 'ASC');
170
  $collection->getSelect()->limit($this->_getExportCustomersPageSize(), $numProcTotal);
171
  $collection->load();
172
 
173
  $numProcessed = 0;
174
 
175
+ try {
 
176
 
177
+ $customers = array();
178
+ foreach ($collection as $customer) {
 
179
 
180
+ $customers[] = Mage::getModel('koan_seg/seg_customer')->prepare($customer);
181
+ $numProcessed++;
182
+ }
183
 
184
+ $storeId = Mage::app()
185
+ ->getWebsite($websiteId)
186
+ ->getDefaultGroup()
187
+ ->getDefaultStoreId();
188
+
189
+ Mage::getModel('koan_seg/seg_client')->exportCustomers($customers, $storeId);
190
+
191
+ unset($customers);
192
+ $customers = array();
193
+
194
+
195
+ } Catch (Exception $e) {
196
+
197
+ $msg = sprintf('exportCustomers - Payload %s, %s - %s', $numProcTotal, $this->_getExportCustomersPageSize(), $e->getMessage());
198
+ $errors[] = $msg;
199
+
200
+ $data = array(
201
+ 'batch_id' => $batch->getId(),
202
+ 'start' => $numProcTotal,
203
+ 'limit' => $this->_getExportCustomersPageSize(),
204
+ 'comment' => $e->getMessage(),
205
+ 'num_retried' => 0
206
+ );
207
+
208
+ $log = Mage::getModel('koan_seg/batch_log');
209
+ $log->setData($data);
210
+ $log->save();
211
+
212
+ Mage::getSingleton('koan_seg/exception_handler')->handle(sprintf('Magento: error in batch exporter - exportCustomers - Payload %s, %s', $numProcTotal, $this->_getExportCustomersPageSize()), new Koan_Seg_Model_Singlepayload_Exception($e->getMessage()));
213
+
214
+ }
215
 
216
  $numProcTotal += $numProcessed;
217
  $batch->updateNumRowsProcessed(null, $numProcessed);
226
 
227
  }
228
 
229
+ return $errors;
230
+ }
231
+
232
+ private function _retryExportCustomers($batch)
233
+ {
234
+ $retryCollection = Mage::getModel('koan_seg/batch_log')->getCollection();
235
+ $retryCollection->addFieldToFilter('batch_id', $batch->getId());
236
+ $retryCollection->addFieldToFilter('num_retried', array('lt' => 3));
237
+
238
+ $cnt = $retryCollection->getSize();
239
+ if (!$cnt) {
240
+ return;
241
+ }
242
+
243
+ $websiteId = $batch->getWebsiteId();
244
+
245
+ foreach ($retryCollection as $retry) {
246
+
247
+ $collection = clone $this->_getCustomersCollection($batch);
248
+ $collection->setOrder('entity_id', 'ASC');
249
+ $collection->getSelect()->limit($retry->getLimit(), $retry->getStart());
250
+ $collection->load();
251
+
252
+ try {
253
+
254
+ $customers = array();
255
+ foreach ($collection as $customer) {
256
+ $customers[] = Mage::getModel('koan_seg/seg_customer')->prepare($customer);
257
+ }
258
+
259
+ $storeId = Mage::app()
260
+ ->getWebsite($websiteId)
261
+ ->getDefaultGroup()
262
+ ->getDefaultStoreId();
263
+
264
+ Mage::getModel('koan_seg/seg_client')->exportCustomers($customers, $storeId);
265
+
266
+ unset($customers);
267
+ $customers = array();
268
+
269
+ } Catch (Exception $e) {
270
+
271
+ $numRetried = $retry->getNumRetried();
272
+ $numRetried = empty($numRetried) ? 0 : $numRetried;
273
+
274
+ $retry->setNumRetried($numRetried + 1);
275
+ $retry->setComment($retry->getComment() . PHP_EOL . $e->getMessage());
276
+ $retry->save();
277
+
278
+ Mage::getSingleton('koan_seg/exception_handler')->handle(sprintf('Magento: error in batch exporter - exportCustomers - Payload %s, %s', $retry->getStart(), $retry->getLimit()), new Koan_Seg_Model_Singlepayload_Exception($e->getMessage()));
279
+
280
+ }
281
+
282
+ }
283
+
284
+ //Check if there are any retries???
285
+
286
+ $retryCollection = Mage::getModel('koan_seg/batch_log')->getCollection();
287
+ $retryCollection->addFieldToFilter('batch_id', $batch->getId());
288
+ $retryCollection->addFieldToFilter('num_retried', array('lt' => 3));
289
+
290
+ $cnt = $retryCollection->getSize();
291
+ if (!$cnt) {
292
+ Mage::throwException('ERROR: Exhausted num retries!');
293
+ }
294
+
295
  }
296
 
297
  private function _getExportCustomersPageSize()
304
  /**************************************** ORDERS ******************************************/
305
 
306
  //Prepare new history orders batch to export
307
+ public function generateHistoryOrdersExportBatch($websiteId, $orderDateFilter = null)
308
  {
309
  if (self::$_exportHistoryOrdersGenerateCron == true) {
310
  return $this;
313
  $this->_getHelper()->initRollbar();
314
 
315
  try {
316
+ $this->_exportHistoryOrders(true, $orderDateFilter, $websiteId);
317
  } Catch (Exception $e) {
318
  Mage::getSingleton('koan_seg/exception_handler')->handle('Magento: error in generateHistoryOrdersExportBatch', $e);
319
  }
348
  return $this;
349
  }
350
 
351
+ private function _exportHistoryOrders($createNew = false, $orderDateFilter = null, $websiteId = null)
352
  {
353
  if ($createNew == true) {
354
+ Mage::getModel('koan_seg/batch_status')->createNew($websiteId, self::BATCH_ENTITY_TYPE_HISTORY_ORDERS, $orderDateFilter);
355
  return $this;
356
  }
357
 
362
  }
363
 
364
  foreach ($batchRows as $batch) {
365
+
366
+ $this->_historyOrdersCollection = null;
367
+
368
  try {
369
  $currentStatus = $batch->getCurrentStatus();
370
 
375
  case self::BATCH_STATUS_STARTING:
376
  $batch->setProcessingStatus(self::BATCH_STATUS_PROCESSING_ROWS);
377
  case self::BATCH_STATUS_PROCESSING_ROWS:
378
+ $errors = $this->_processExportHistoryOrders($batch);
379
+ if (count($errors)) {
380
+ $batch->setBatchRetryError('Some errors occured during the batch export. Pending retry.');
381
+ } else {
382
+ $batch->setCompleteStatus(self::BATCH_STATUS_COMPLETE);
383
+ }
384
+ break;
385
+ case self::BATCH_STATUS_NEED_RETRY:
386
+ $this->_retryExportHistoryOrders($batch);
387
+ break;
388
  }
389
 
390
  } Catch (Exception $e) {
397
  return $this;
398
  }
399
 
400
+ private function _retryExportHistoryOrders($batch)
401
+ {
402
+ $retryCollection = Mage::getModel('koan_seg/batch_log')->getCollection();
403
+ $retryCollection->addFieldToFilter('batch_id', $batch->getId());
404
+ $retryCollection->addFieldToFilter('num_retried', array('lt' => 3));
405
+
406
+ $cnt = $retryCollection->getSize();
407
+ if (!$cnt) {
408
+ return;
409
+ }
410
+
411
+ foreach ($retryCollection as $retry) {
412
+
413
+ $collection = clone $this->_getHistoryOrdersCollection($batch);
414
+ $collection->setOrder('entity_id', 'ASC');
415
+ $collection->getSelect()->limit($retry->getLimit(), $retry->getStart());
416
+ $collection->load();
417
+
418
+ try {
419
+
420
+ $orders = array();
421
+ foreach ($collection as $order) {
422
+ $orders[] = Mage::getModel('koan_seg/seg_order')->prepare($order);
423
+ }
424
+
425
+ $websiteId = $batch->getWebsiteId();
426
+ $storeId = Mage::app()
427
+ ->getWebsite($websiteId)
428
+ ->getDefaultGroup()
429
+ ->getDefaultStoreId();
430
+
431
+ Mage::getModel('koan_seg/seg_client')->exportHistoryOrders($orders, $storeId);
432
+
433
+ unset($orders);
434
+ $orders = array();
435
+
436
+ } Catch (Exception $e) {
437
+
438
+ $numRetried = $retry->getNumRetried();
439
+ $numRetried = empty($numRetried) ? 0 : $numRetried;
440
+
441
+ $retry->setNumRetried($numRetried + 1);
442
+ $retry->setComment($retry->getComment() . PHP_EOL . $e->getMessage());
443
+ $retry->save();
444
+
445
+ Mage::getSingleton('koan_seg/exception_handler')->handle(sprintf('Magento: error in batch exporter - exportHistoryOrders - Payload %s, %s', $retry->getStart(), $retry->getLimit()), new Koan_Seg_Model_Singlepayload_Exception($e->getMessage()));
446
+
447
+ }
448
+
449
+ }
450
+
451
+ //Check if there are any retries???
452
+
453
+ $retryCollection = Mage::getModel('koan_seg/batch_log')->getCollection();
454
+ $retryCollection->addFieldToFilter('batch_id', $batch->getId());
455
+ $retryCollection->addFieldToFilter('num_retried', array('lt' => 3));
456
+
457
+ $cnt = $retryCollection->getSize();
458
+ if (!$cnt) {
459
+ Mage::throwException('ERROR: Exhausted num retries!');
460
+ }
461
+
462
+ }
463
+
464
  private function _processExportHistoryOrders($batch)
465
  {
466
+ $errors = array();
467
+
468
  $numProcTotal = is_null($batch->getNumRowsProcessed()) ? 0 : intval($batch->getNumRowsProcessed());
469
  $totalRows = is_null($batch->getTotalRowCount()) ? 0 : intval($batch->getTotalRowCount());
470
 
481
 
482
  $numProcessed = 0;
483
 
484
+ try {
 
485
 
486
+ $orders = array();
487
+ foreach ($collection as $order) {
 
 
488
 
489
+ //TODO: Handle collection export
490
+ $orders[] = Mage::getModel('koan_seg/seg_order')->prepare($order);
491
+ $numProcessed++;
492
+ }
493
 
494
+ $websiteId = $batch->getWebsiteId();
495
+ $storeId = Mage::app()
496
+ ->getWebsite($websiteId)
497
+ ->getDefaultGroup()
498
+ ->getDefaultStoreId();
499
+
500
+ Mage::getModel('koan_seg/seg_client')->exportHistoryOrders($orders, $storeId);
501
+
502
+ unset($orders);
503
+ $orders = array();
504
+
505
+ } Catch (Exception $e) {
506
+
507
+ $msg = sprintf('exportHistoryOrders - Payload %s, %s - %s', $numProcTotal, $this->_getExportHistoryPageSize(), $e->getMessage());
508
+ $errors[] = $msg;
509
+
510
+ $data = array(
511
+ 'batch_id' => $batch->getId(),
512
+ 'start' => $numProcTotal,
513
+ 'limit' => $this->_getExportHistoryPageSize(),
514
+ 'comment' => $e->getMessage(),
515
+ 'num_retried' => 0
516
+ );
517
+
518
+ $log = Mage::getModel('koan_seg/batch_log');
519
+ $log->setData($data);
520
+ $log->save();
521
+
522
+ Mage::getSingleton('koan_seg/exception_handler')->handle(sprintf('Magento: error in batch exporter - exportHistoryOrders - Payload %s, %s', $numProcTotal, $this->_getExportHistoryPageSize()), new Koan_Seg_Model_Singlepayload_Exception($e->getMessage()));
523
+
524
+ }
525
 
526
  $numProcTotal += $numProcessed;
527
  $batch->updateNumRowsProcessed(null, $numProcessed);
535
 
536
  }
537
 
538
+ return $errors;
539
  }
540
 
541
  private function _getExportHistoryPageSize()
568
  $allowedStages = array(
569
  self::BATCH_STATUS_NOT_STARTED,
570
  self::BATCH_STATUS_STARTING,
571
+ self::BATCH_STATUS_PROCESSING_ROWS,
572
+ self::BATCH_STATUS_NEED_RETRY,
573
  );
574
 
575
  $collection = Mage::getResourceModel('koan_seg/batch_status_collection');
587
 
588
  public function _getHistoryOrdersCollection($batch = null)
589
  {
590
+ $websiteId = $batch->getWebsiteId();
591
+ $storeId = Mage::app()
592
+ ->getWebsite($websiteId)
593
+ ->getDefaultGroup()
594
+ ->getDefaultStoreId();
595
+
596
  if (!$this->_historyOrdersCollection) {
597
  $collection = Mage::getResourceModel('sales/order_collection');
598
+
599
+ $allowedStatuses = $this->_getHelper()->getOrdersExportStatuses($storeId);
600
+ if ($allowedStatuses AND is_array($allowedStatuses) AND count($allowedStatuses)) {
601
+ $collection->addFieldToFilter('status', array('in' => $allowedStatuses));
602
+ } else {
603
+ $collection->addFieldToFilter('state', 'complete');
604
+ }
605
+
606
+ $storeIds = Mage::app()->getWebsite($websiteId)->getStoreIds();
607
+ $collection->addFieldToFilter('store_id', array('in' => $storeIds));
608
 
609
  if ($batch AND $filter = $batch->getFilter()) {
610
  $collection->addFieldToFilter('created_at', array('from' => $filter));
app/code/community/Koan/Seg/Model/Seg/Order/Line.php CHANGED
@@ -40,7 +40,8 @@ class Koan_Seg_Model_Seg_Order_Line extends Varien_Object
40
  $price = $originalPrice;
41
  }
42
 
43
- $this->setData('Quantity', number_format($qty, 2, '.', ''));
 
44
  $this->setData('Id', $item->getProductId());
45
  $this->setData('ImageUrl', $product->getImageUrl());
46
 
@@ -87,32 +88,35 @@ class Koan_Seg_Model_Seg_Order_Line extends Varien_Object
87
  'Price',
88
  );
89
 
90
- $brands = $this->_getHelper()->getProductBrands($product, $item->getStoreId());
91
- if (!empty($brands)) {
92
- $this->setData('Brands', $brands);
93
- $outputAttributes[] = 'Brands';
94
- }
95
 
96
  if (!empty($variantName)) {
97
  $outputAttributes[] = 'VariantName';
98
  }
99
 
100
- $catIds = $product->getCategoryIds();
101
- $categoriesResult = array();
102
- if ($catIds AND is_array($catIds) AND count($catIds)) {
103
- foreach ($catIds as $catId) {
104
- $category = Mage::getModel('catalog/category')
105
- ->setStoreId($item->getStoreId())
106
- ->load($catId);
107
-
108
- if ($category AND $category->getId()) {
109
- $categoriesResult[] = $category->getName();
110
- }
 
 
 
 
 
 
111
  }
112
  }
113
- if (count($categoriesResult)) {
114
- $this->setData('Categories', $categoriesResult);
115
- $outputAttributes[] = 'Categories';
 
116
  }
117
 
118
  return $this->toArray($outputAttributes);
40
  $price = $originalPrice;
41
  }
42
 
43
+ //$this->setData('Quantity', number_format($qty, 2, '.', ''));
44
+ $this->setData('Quantity', intval($qty));
45
  $this->setData('Id', $item->getProductId());
46
  $this->setData('ImageUrl', $product->getImageUrl());
47
 
88
  'Price',
89
  );
90
 
91
+ $tags = $this->_getHelper()->getProductTags($product, $item->getStoreId());
 
 
 
 
92
 
93
  if (!empty($variantName)) {
94
  $outputAttributes[] = 'VariantName';
95
  }
96
 
97
+ // $catIds = $product->getCategoryIds();
98
+ // if ($catIds AND is_array($catIds) AND count($catIds)) {
99
+ // foreach ($catIds as $catId) {
100
+ // $category = Mage::getModel('catalog/category')
101
+ // ->setStoreId($item->getStoreId())
102
+ // ->load($catId);
103
+ //
104
+ // if ($category AND $category->getId()) {
105
+ // $tags[] = $category->getName();
106
+ // }
107
+ // }
108
+ // }
109
+
110
+ $categories = Mage::helper('koan_seg')->getAllProductCategories($product);
111
+ if ($categories AND is_array($categories) AND count($categories)) {
112
+ foreach ($categories as $catName) {
113
+ $tags[] = $catName;
114
  }
115
  }
116
+
117
+ if (!empty($tags)) {
118
+ $this->setData('Tags', @array_values($tags));
119
+ $outputAttributes[] = 'Tags';
120
  }
121
 
122
  return $this->toArray($outputAttributes);
app/code/community/Koan/Seg/Model/Seg/Product.php CHANGED
@@ -35,28 +35,30 @@ class Koan_Seg_Model_Seg_Product extends Varien_Object
35
 
36
  $this->setData($productData);
37
 
38
- $catIds = $product->getCategoryIds();
39
- $categoriesResult = array();
40
- if ($catIds AND is_array($catIds) AND count($catIds)) {
41
- foreach ($catIds as $catId) {
42
- $category = Mage::getModel('catalog/category')
43
- ->setStoreId($storeId)
44
- ->load($catId);
45
 
46
- if ($category AND $category->getId()) {
47
- $categoriesResult[] = $category->getName();
48
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
  }
51
- if (count($categoriesResult)) {
52
- $this->setData('Categories', $categoriesResult);
53
- $outputAttributes[] = 'Categories';
54
- }
55
 
56
- $brands = $this->_getHelper()->getProductBrands($product, $storeId);
57
- if (!empty($brands)) {
58
- $this->setData('Brands', $brands);
59
- $outputAttributes[] = 'Brands';
60
  }
61
 
62
  return $this->toArray($outputAttributes);
35
 
36
  $this->setData($productData);
37
 
38
+ $tags = $this->_getHelper()->getProductTags($product, $storeId);
 
 
 
 
 
 
39
 
40
+ // $catIds = $product->getCategoryIds();
41
+ // if ($catIds AND is_array($catIds) AND count($catIds)) {
42
+ // foreach ($catIds as $catId) {
43
+ // $category = Mage::getModel('catalog/category')
44
+ // ->setStoreId($storeId)
45
+ // ->load($catId);
46
+ //
47
+ // if ($category AND $category->getId()) {
48
+ // $tags[] = $category->getName();
49
+ // }
50
+ // }
51
+ // }
52
+ $categories = Mage::helper('koan_seg')->getAllProductCategories($product);
53
+ if ($categories AND is_array($categories) AND count($categories)) {
54
+ foreach ($categories as $catName) {
55
+ $tags[] = $catName;
56
  }
57
  }
 
 
 
 
58
 
59
+ if (!empty($tags)) {
60
+ $this->setData('Tags', @array_values($tags));
61
+ $outputAttributes[] = 'Tags';
 
62
  }
63
 
64
  return $this->toArray($outputAttributes);
app/code/community/Koan/Seg/Model/Seg/Quote/Line.php CHANGED
@@ -49,7 +49,8 @@ class Koan_Seg_Model_Seg_Quote_Line extends Varien_Object
49
  $price = $originalPrice;
50
  }
51
 
52
- $this->setData('Quantity', number_format($qty, 2, '.', ''));
 
53
  $this->setData('Id', $item->getProductId());
54
  $this->setData('ImageUrl', $product->getImageUrl());
55
 
@@ -96,32 +97,40 @@ class Koan_Seg_Model_Seg_Quote_Line extends Varien_Object
96
  'Price',
97
  );
98
 
99
- $brands = $this->_getHelper()->getProductBrands($product, $item->getStoreId());
100
- if (!empty($brands)) {
101
- $this->setData('Brands', $brands);
102
- $outputAttributes[] = 'Brands';
103
- }
104
 
105
  if (!empty($variantName)) {
106
  $outputAttributes[] = 'VariantName';
107
  }
108
 
109
- $catIds = $product->getCategoryIds();
110
- $categoriesResult = array();
111
- if ($catIds AND is_array($catIds) AND count($catIds)) {
112
- foreach ($catIds as $catId) {
113
- $category = Mage::getModel('catalog/category')
114
- ->setStoreId($item->getStoreId())
115
- ->load($catId);
 
 
 
 
 
116
 
117
- if ($category AND $category->getId()) {
118
- $categoriesResult[] = $category->getName();
119
- }
 
 
 
 
 
 
120
  }
121
  }
122
- if (count($categoriesResult)) {
123
- $this->setData('Categories', $categoriesResult);
124
- $outputAttributes[] = 'Categories';
 
125
  }
126
 
127
  if ($isAdded == true) {
49
  $price = $originalPrice;
50
  }
51
 
52
+ // $this->setData('Quantity', number_format($qty, 2, '.', ''));
53
+ $this->setData('Quantity', intval($qty));
54
  $this->setData('Id', $item->getProductId());
55
  $this->setData('ImageUrl', $product->getImageUrl());
56
 
97
  'Price',
98
  );
99
 
100
+ $tags = $this->_getHelper()->getProductTags($product, $item->getStoreId());
 
 
 
 
101
 
102
  if (!empty($variantName)) {
103
  $outputAttributes[] = 'VariantName';
104
  }
105
 
106
+ // $catIds = $product->getCategoryIds();
107
+ // if ($catIds AND is_array($catIds) AND count($catIds)) {
108
+ // foreach ($catIds as $catId) {
109
+ // $category = Mage::getModel('catalog/category')
110
+ // ->setStoreId($item->getStoreId())
111
+ // ->load($catId);
112
+ //
113
+ // if ($category AND $category->getId()) {
114
+ // $tags[] = $category->getName();
115
+ // }
116
+ // }
117
+ // }
118
 
119
+ if ($parentProduct) {
120
+ $categories = Mage::helper('koan_seg')->getAllProductCategories($parentProduct);
121
+ } else {
122
+ $categories = Mage::helper('koan_seg')->getAllProductCategories($product);
123
+ }
124
+
125
+ if ($categories AND is_array($categories) AND count($categories)) {
126
+ foreach ($categories as $catName) {
127
+ $tags[] = $catName;
128
  }
129
  }
130
+
131
+ if (!empty($tags)) {
132
+ $this->setData('Tags', @array_values($tags));
133
+ $outputAttributes[] = 'Tags';
134
  }
135
 
136
  if ($isAdded == true) {
app/code/community/Koan/Seg/Model/Seg/Range.php CHANGED
@@ -19,7 +19,7 @@ class Koan_Seg_Model_Seg_Range extends Varien_Object
19
  Mage::throwException('Missing Category Id');
20
  }
21
 
22
- $categoryData = array('Categories');
23
 
24
  $lastCatName = $category->getName();
25
  $lastCategoryAdjust = 1;
@@ -32,14 +32,34 @@ class Koan_Seg_Model_Seg_Range extends Varien_Object
32
  $cat = Mage::getModel('catalog/category')->load($path[$i]);
33
  if ($cat && $cat->getIsActive()) {
34
 
35
- $categoryData['Categories'][] = $cat->getName();
36
  }
37
  }
38
 
39
- $categoryData['Categories'][] = $lastCatName;
40
  }
41
 
42
- $this->setData($categoryData);
43
- return $this->toArray(array('Categories'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
45
  }
19
  Mage::throwException('Missing Category Id');
20
  }
21
 
22
+ $tagData = array('Tags');
23
 
24
  $lastCatName = $category->getName();
25
  $lastCategoryAdjust = 1;
32
  $cat = Mage::getModel('catalog/category')->load($path[$i]);
33
  if ($cat && $cat->getIsActive()) {
34
 
35
+ $tagData['Tags'][] = $cat->getName();
36
  }
37
  }
38
 
39
+ $tagData['Tags'][] = $lastCatName;
40
  }
41
 
42
+
43
+ $appliedFilters = Mage::getSingleton('catalog/layer')->getState()->getFilters();
44
+
45
+ $tagAttributeCodes = Mage::helper('koan_seg')->getTagAttributeCodes(Mage::app()->getStore()->getId());
46
+ if ($tagAttributeCodes) {
47
+ $tagAttributeCodes = array_map('trim', explode(',', $tagAttributeCodes));
48
+ }
49
+
50
+ if ($appliedFilters AND is_array($appliedFilters) AND count($appliedFilters)) {
51
+ foreach ($appliedFilters as $item) {
52
+ $requestVar = $item->getFilter()->getRequestVar();
53
+ if (!in_array($requestVar, $tagAttributeCodes)) {
54
+ continue;
55
+ }
56
+ $filterValue = $item->getLabel(); // Currently selected value
57
+ $tagData['Tags'][] = $filterValue;
58
+ }
59
+
60
+ }
61
+
62
+ $this->setData($tagData);
63
+ return $this->toArray(array('Tags'));
64
  }
65
  }
app/code/community/Koan/Seg/Model/Singlepayload/Exception.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+
4
+ class Koan_Seg_Model_Singlepayload_Exception extends Exception
5
+ {
6
+
7
+ }
app/code/community/Koan/Seg/Model/System/Config/Source/Attributes.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Koan_Seg_Model_System_Config_Source_Attributes
4
+ {
5
+
6
+ // public function toOptionArray()
7
+ // {
8
+ // return array(
9
+ // array('value' => 1, 'label'=>Mage::helper('adminhtml')->__('Yes')),
10
+ // array('value' => 0, 'label'=>Mage::helper('adminhtml')->__('No')),
11
+ // );
12
+ // }
13
+
14
+ private function _getProductAttributes()
15
+ {
16
+ $attributes = Mage::getResourceModel('catalog/product_attribute_collection')
17
+ ->addVisibleFilter()
18
+ ->getItems();
19
+
20
+ return $attributes;
21
+ }
22
+
23
+ private function getSkippedAttributes()
24
+ {
25
+ return array(
26
+ 'name',
27
+ 'description',
28
+ 'short_description',
29
+ 'sku',
30
+ 'weight',
31
+ 'news_from_date',
32
+ 'new_to_date',
33
+ 'status',
34
+ 'url_key',
35
+ 'visibility',
36
+ 'open_amount_min',
37
+ 'open_amount_max',
38
+ 'price',
39
+ 'group_price',
40
+ 'special_price',
41
+ 'special_from_date',
42
+ 'special_to_date',
43
+ 'cost',
44
+ 'tier_price',
45
+ 'msrp_enabled',
46
+ 'msrp_display_actual_price_type',
47
+ 'msrp',
48
+ 'tax_class_id',
49
+ 'price_view',
50
+ 'meta_title',
51
+ 'meta_keyword',
52
+ 'meta_description',
53
+ 'image',
54
+ 'small_image',
55
+ 'thumbnail',
56
+ 'media_gallery',
57
+ 'gallery',
58
+ 'is_recurring',
59
+ 'recurring_profile',
60
+ 'custom_design',
61
+ 'custom_design_from',
62
+ 'custom_design_to',
63
+ 'custom_layout_update',
64
+ 'page_layout',
65
+ 'options_container',
66
+ 'gift_message_available',
67
+ 'gift_wrapping_available',
68
+ 'gift_wrapping_price',
69
+ 'use_config_allow_message',
70
+ 'use_config_email_template',
71
+ 'use_config_is_redeemable',
72
+ 'use_config_lifetime',
73
+ 'weight_type',
74
+ 'url_path'
75
+
76
+ );
77
+ }
78
+
79
+ public function toOptionArray()
80
+ {
81
+ $result = array();
82
+
83
+ foreach ($this->_getProductAttributes() as $attribute) {
84
+
85
+ if (in_array($attribute->getName(), $this->getSkippedAttributes())) {
86
+ continue;
87
+ }
88
+
89
+ $result[] = array('label' => $attribute->getName(), 'value' => $attribute->getName());
90
+ }
91
+
92
+ return $result;
93
+
94
+ }
95
+
96
+ }
app/code/community/Koan/Seg/controllers/Adminhtml/SegController.php CHANGED
@@ -16,6 +16,26 @@ class Koan_Seg_Adminhtml_SegController extends Mage_Adminhtml_Controller_Action
16
 
17
  }
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  public function exporterAction()
20
  {
21
  $this->_checkIfCronActivated();
@@ -29,21 +49,27 @@ class Koan_Seg_Adminhtml_SegController extends Mage_Adminhtml_Controller_Action
29
  {
30
  $exporter = Mage::getSingleton('koan_seg/seg_exporter');
31
 
32
- $batchCollection = Mage::getResourceModel('koan_seg/batch_status_collection');
33
- $batchCollection->addFieldToFilter('entity_type', 'customers');
34
- $batchCollection->addFieldToFilter('current_status',
35
- array('nin' => array(Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_COMPLETE, Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR)
36
- ));
37
-
38
  try {
39
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  $isRunning = $batchCollection->getSize();
41
  if ($isRunning) {
42
  Mage::throwException('Can not start new batch while one is still running. Please try again later!');
43
  return;
44
  }
45
 
46
- $exporter->generateCustomersExportBatch();
47
  $msg = Mage::helper('koan_seg')->__('New batch has been scheduled successfully. Export will start with new CRON job in several minutes.');
48
 
49
  Mage::getSingleton('adminhtml/session')->addSuccess($msg);
@@ -59,23 +85,29 @@ class Koan_Seg_Adminhtml_SegController extends Mage_Adminhtml_Controller_Action
59
  {
60
  $orderDateFilter = null;
61
 
62
- $fromDateFiter = $this->getRequest()->getParam('order_date_from');
63
- if ($fromDateFiter AND $fromDateFiter != 'NO_FILTER') {
64
- $filter = @json_decode($fromDateFiter, true);
65
- if ($filter AND is_array($filter) AND isset($filter['date'])) {
66
- $orderDateFilter = $filter['date'];
67
  }
68
- }
69
 
70
- $exporter = Mage::getSingleton('koan_seg/seg_exporter');
 
 
 
 
 
 
71
 
72
- $batchCollection = Mage::getResourceModel('koan_seg/batch_status_collection');
73
- $batchCollection->addFieldToFilter('entity_type', 'history_orders');
74
- $batchCollection->addFieldToFilter('current_status',
75
- array('nin' => array(Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_COMPLETE, Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR)
76
- ));
77
 
78
- try {
 
 
 
 
 
79
 
80
  $isRunning = $batchCollection->getSize();
81
  if ($isRunning) {
@@ -83,7 +115,7 @@ class Koan_Seg_Adminhtml_SegController extends Mage_Adminhtml_Controller_Action
83
  return;
84
  }
85
 
86
- $exporter->generateHistoryOrdersExportBatch($orderDateFilter);
87
  $msg = Mage::helper('koan_seg')->__('New batch has been scheduled successfully. Export will start with new CRON job in several minutes.');
88
 
89
  Mage::getSingleton('adminhtml/session')->addSuccess($msg);
16
 
17
  }
18
 
19
+ public function logAction()
20
+ {
21
+ $batchId = $this->getRequest()->getParam('id', null);
22
+ $block = $this->getLayout()->createBlock('core/template', 'log_list');
23
+
24
+ if ($batchId) {
25
+
26
+ $collection = Mage::getModel('koan_seg/batch_log')->getCollection();
27
+ $collection->addFieldToFilter('batch_id', $batchId);
28
+ $collection->getSelect()->order('id ASC');
29
+
30
+ $block->setLogCollection($collection);
31
+ }
32
+
33
+ $block->setTemplate('seg/log.phtml');
34
+ $this->getResponse()->setBody($block->toHtml());
35
+
36
+ return;
37
+ }
38
+
39
  public function exporterAction()
40
  {
41
  $this->_checkIfCronActivated();
49
  {
50
  $exporter = Mage::getSingleton('koan_seg/seg_exporter');
51
 
 
 
 
 
 
 
52
  try {
53
 
54
+ $websiteId = $this->getRequest()->getParam('website', null);
55
+ if (!$websiteId) {
56
+ Mage::throwException('Website Id not set properly!');
57
+ }
58
+
59
+ $batchCollection = Mage::getResourceModel('koan_seg/batch_status_collection');
60
+ $batchCollection->addFieldToFilter('entity_type', 'customers');
61
+ $batchCollection->addFieldToFilter('website_id', $websiteId);
62
+
63
+ $batchCollection->addFieldToFilter('current_status',
64
+ array('nin' => array(Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_COMPLETE, Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR)));
65
+
66
  $isRunning = $batchCollection->getSize();
67
  if ($isRunning) {
68
  Mage::throwException('Can not start new batch while one is still running. Please try again later!');
69
  return;
70
  }
71
 
72
+ $exporter->generateCustomersExportBatch($websiteId);
73
  $msg = Mage::helper('koan_seg')->__('New batch has been scheduled successfully. Export will start with new CRON job in several minutes.');
74
 
75
  Mage::getSingleton('adminhtml/session')->addSuccess($msg);
85
  {
86
  $orderDateFilter = null;
87
 
88
+ try {
89
+
90
+ $websiteId = $this->getRequest()->getParam('website', null);
91
+ if (!$websiteId) {
92
+ Mage::throwException('Website Id not set properly!');
93
  }
 
94
 
95
+ $fromDateFiter = $this->getRequest()->getParam('order_date_from');
96
+ if ($fromDateFiter AND $fromDateFiter != 'NO_FILTER') {
97
+ $filter = @json_decode($fromDateFiter, true);
98
+ if ($filter AND is_array($filter) AND isset($filter['date'])) {
99
+ $orderDateFilter = $filter['date'];
100
+ }
101
+ }
102
 
103
+ $exporter = Mage::getSingleton('koan_seg/seg_exporter');
 
 
 
 
104
 
105
+ $batchCollection = Mage::getResourceModel('koan_seg/batch_status_collection');
106
+ $batchCollection->addFieldToFilter('entity_type', 'history_orders');
107
+ $batchCollection->addFieldToFilter('website_id', $websiteId);
108
+ $batchCollection->addFieldToFilter('current_status',
109
+ array('nin' => array(Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_COMPLETE, Koan_Seg_Model_Seg_Exporter::BATCH_STATUS_ERROR)
110
+ ));
111
 
112
  $isRunning = $batchCollection->getSize();
113
  if ($isRunning) {
115
  return;
116
  }
117
 
118
+ $exporter->generateHistoryOrdersExportBatch($websiteId, $orderDateFilter);
119
  $msg = Mage::helper('koan_seg')->__('New batch has been scheduled successfully. Export will start with new CRON job in several minutes.');
120
 
121
  Mage::getSingleton('adminhtml/session')->addSuccess($msg);
app/code/community/Koan/Seg/etc/adminhtml.xml CHANGED
@@ -20,6 +20,8 @@
20
  </children>
21
  </system>
22
  <seg translate="title" module="koan_seg">
 
 
23
  <children>
24
  <exporter>
25
  <title>Exporter</title>
20
  </children>
21
  </system>
22
  <seg translate="title" module="koan_seg">
23
+ <title>Seg</title>
24
+ <sort_order>120</sort_order>
25
  <children>
26
  <exporter>
27
  <title>Exporter</title>
app/code/community/Koan/Seg/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Koan_Seg>
5
- <version>1.0.0.2</version>
6
  </Koan_Seg>
7
  </modules>
8
  <global>
@@ -22,6 +22,9 @@
22
  <batch_status>
23
  <table>seg_batch_status</table>
24
  </batch_status>
 
 
 
25
  </entities>
26
  </koan_seg_resource>
27
  </models>
2
  <config>
3
  <modules>
4
  <Koan_Seg>
5
+ <version>1.1.1.0</version>
6
  </Koan_Seg>
7
  </modules>
8
  <global>
22
  <batch_status>
23
  <table>seg_batch_status</table>
24
  </batch_status>
25
+ <batch_log>
26
+ <table>seg_batch_log</table>
27
+ </batch_log>
28
  </entities>
29
  </koan_seg_resource>
30
  </models>
app/code/community/Koan/Seg/etc/system.xml CHANGED
@@ -12,7 +12,7 @@
12
  <tab>koan_seg</tab>
13
  <sort_order>1000</sort_order>
14
  <show_in_default>1</show_in_default>
15
- <show_in_website>0</show_in_website>
16
  <show_in_store>0</show_in_store>
17
  <groups>
18
  <general translate="label" module="koan_seg">
@@ -27,9 +27,10 @@
27
  <label>Seg Website Id</label>
28
  <frontend_type>text</frontend_type>
29
  <sort_order>100</sort_order>
30
- <show_in_default>1</show_in_default>
31
- <show_in_website>0</show_in_website>
32
  <show_in_store>0</show_in_store>
 
33
  <comment><![CDATA[<a href="https://www.segapp.com/signup" target="_blank">Not yet registered with Seg? Click here to create account</a>]]></comment>
34
  </seg_website_id>
35
  <orders_export_batch_size translate="label">
@@ -40,6 +41,15 @@
40
  <show_in_website>0</show_in_website>
41
  <show_in_store>0</show_in_store>
42
  </orders_export_batch_size>
 
 
 
 
 
 
 
 
 
43
  <customers_export_batch_size translate="label">
44
  <label>Customers export batch size</label>
45
  <frontend_type>text</frontend_type>
@@ -48,15 +58,25 @@
48
  <show_in_website>0</show_in_website>
49
  <show_in_store>0</show_in_store>
50
  </customers_export_batch_size>
51
- <brand_attr_code translate="label">
52
- <label>"Brand" attribute code</label>
53
- <frontend_type>text</frontend_type>
 
 
 
 
 
 
 
 
 
54
  <sort_order>130</sort_order>
55
- <show_in_default>1</show_in_default>
56
- <show_in_website>0</show_in_website>
57
  <show_in_store>0</show_in_store>
58
- <comment>Code of attribute which represents product brand</comment>
59
- </brand_attr_code>
 
60
  <rollbar_report_params translate="label">
61
  <label>Enable diagnostics logging</label>
62
  <frontend_type>select</frontend_type>
@@ -84,7 +104,7 @@
84
  <frontend_type>text</frontend_type>
85
  <sort_order>150</sort_order>
86
  <show_in_default>1</show_in_default>
87
- <show_in_website>0</show_in_website>
88
  <show_in_store>0</show_in_store>
89
  <fields>
90
  <php_memory_limit>
@@ -96,6 +116,15 @@
96
  <show_in_store>0</show_in_store>
97
  <comment>This is advanced value. Please do not change unless don't know what are you doing! Leave empty or 0 to turn Off</comment>
98
  </php_memory_limit>
 
 
 
 
 
 
 
 
 
99
  </fields>
100
  </advanced>
101
  </groups>
12
  <tab>koan_seg</tab>
13
  <sort_order>1000</sort_order>
14
  <show_in_default>1</show_in_default>
15
+ <show_in_website>1</show_in_website>
16
  <show_in_store>0</show_in_store>
17
  <groups>
18
  <general translate="label" module="koan_seg">
27
  <label>Seg Website Id</label>
28
  <frontend_type>text</frontend_type>
29
  <sort_order>100</sort_order>
30
+ <show_in_default>0</show_in_default>
31
+ <show_in_website>1</show_in_website>
32
  <show_in_store>0</show_in_store>
33
+ <backend_model>koan_seg/guid_validator</backend_model>
34
  <comment><![CDATA[<a href="https://www.segapp.com/signup" target="_blank">Not yet registered with Seg? Click here to create account</a>]]></comment>
35
  </seg_website_id>
36
  <orders_export_batch_size translate="label">
41
  <show_in_website>0</show_in_website>
42
  <show_in_store>0</show_in_store>
43
  </orders_export_batch_size>
44
+ <orders_export_statuses translate="label">
45
+ <label>Export orders that have status</label>
46
+ <frontend_type>multiselect</frontend_type>
47
+ <source_model>adminhtml/system_config_source_order_status</source_model>
48
+ <sort_order>115</sort_order>
49
+ <show_in_default>1</show_in_default>
50
+ <show_in_website>1</show_in_website>
51
+ <show_in_store>0</show_in_store>
52
+ </orders_export_statuses>
53
  <customers_export_batch_size translate="label">
54
  <label>Customers export batch size</label>
55
  <frontend_type>text</frontend_type>
58
  <show_in_website>0</show_in_website>
59
  <show_in_store>0</show_in_store>
60
  </customers_export_batch_size>
61
+ <!--<tag_attr_codes translate="label">-->
62
+ <!--<label>"Tag" attribute codes</label>-->
63
+ <!--<frontend_type>text</frontend_type>-->
64
+ <!--<sort_order>130</sort_order>-->
65
+ <!--<show_in_default>0</show_in_default>-->
66
+ <!--<show_in_website>1</show_in_website>-->
67
+ <!--<show_in_store>0</show_in_store>-->
68
+ <!--<comment>Comma separated attribute codes which represent product tags</comment>-->
69
+ <!--</tag_attr_codes>-->
70
+ <tag_attr_codes translate="label">
71
+ <label>"Tag" attribute codes</label>
72
+ <frontend_type>multiselect</frontend_type>
73
  <sort_order>130</sort_order>
74
+ <show_in_default>0</show_in_default>
75
+ <show_in_website>1</show_in_website>
76
  <show_in_store>0</show_in_store>
77
+ <source_model>koan_seg/system_config_source_attributes</source_model>
78
+ <comment>Attribute codes which represent product tags</comment>
79
+ </tag_attr_codes>
80
  <rollbar_report_params translate="label">
81
  <label>Enable diagnostics logging</label>
82
  <frontend_type>select</frontend_type>
104
  <frontend_type>text</frontend_type>
105
  <sort_order>150</sort_order>
106
  <show_in_default>1</show_in_default>
107
+ <show_in_website>1</show_in_website>
108
  <show_in_store>0</show_in_store>
109
  <fields>
110
  <php_memory_limit>
116
  <show_in_store>0</show_in_store>
117
  <comment>This is advanced value. Please do not change unless don't know what are you doing! Leave empty or 0 to turn Off</comment>
118
  </php_memory_limit>
119
+ <request_timeout>
120
+ <label>Exporter request timeout (seconds)</label>
121
+ <frontend_type>text</frontend_type>
122
+ <sort_order>170</sort_order>
123
+ <show_in_default>1</show_in_default>
124
+ <show_in_website>0</show_in_website>
125
+ <show_in_store>0</show_in_store>
126
+ <comment>This is advanced value. Please do not change unless don't know what are you doing! Leave empty or 0 to turn Off</comment>
127
+ </request_timeout>
128
  </fields>
129
  </advanced>
130
  </groups>
app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.0-1.0.0.1.php CHANGED
@@ -33,3 +33,4 @@ $table = $installer->getConnection()
33
  'nullable' => false
34
  ));
35
  $installer->getConnection()->createTable($table);
 
33
  'nullable' => false
34
  ));
35
  $installer->getConnection()->createTable($table);
36
+ $installer->endSetup();
app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.1-1.0.0.2.php CHANGED
@@ -14,3 +14,4 @@ $installer->getConnection()->addColumn(
14
  'comment' => 'Date filter for orders'
15
  )
16
  );
 
14
  'comment' => 'Date filter for orders'
15
  )
16
  );
17
+ $installer->endSetup();
app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.2-1.0.0.3.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $installer->startSetup();
5
+
6
+ $installer->getConnection()->addColumn(
7
+ $installer->getTable('koan_seg/batch_status'),
8
+ 'website_id',
9
+ array(
10
+ 'type' => Varien_Db_Ddl_Table::TYPE_INTEGER,
11
+ 'nullable' => true,
12
+ 'default' => null,
13
+ 'comment' => 'Website Id'
14
+ )
15
+ );
16
+ $installer->endSetup();
app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.3-1.0.0.4.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $installer->startSetup();
5
+
6
+ $table = $installer->getConnection()
7
+ ->newTable($installer->getTable('koan_seg/batch_log'))
8
+ ->addColumn('id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
9
+ 'identity' => true,
10
+ 'unsigned' => true,
11
+ 'nullable' => false,
12
+ 'primary' => true
13
+ ))
14
+ ->addColumn('batch_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
15
+ 'nullable' => false
16
+ ))
17
+ ->addColumn('start', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
18
+ 'nullable' => false
19
+ ))
20
+ ->addColumn('limit', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
21
+ 'nullable' => false
22
+ ))
23
+ ->addColumn('comment', Varien_Db_Ddl_Table::TYPE_TEXT, null, array(
24
+ 'nullable' => false
25
+ ))
26
+ ->addColumn('num_retried', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
27
+ 'nullable' => false
28
+ ));
29
+ $installer->getConnection()->createTable($table);
30
+ $installer->endSetup();
app/code/community/Koan/Seg/sql/koan_seg_setup/upgrade-1.0.0.4-1.0.0.5.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $installer->startSetup();
5
+
6
+ $installer->getConnection()->addForeignKey(
7
+ $installer->getFkName('koan_seg/batch_log', 'batch_id', 'koan_seg/batch_status', 'id'),
8
+ $installer->getTable('koan_seg/batch_log'),
9
+ 'batch_id',
10
+ $installer->getTable('koan_seg/batch_status'),
11
+ 'id'
12
+ );
13
+
14
+ $installer->endSetup();
app/design/adminhtml/default/default/layout/seg.xml CHANGED
@@ -2,7 +2,7 @@
2
  <layout>
3
  <adminhtml_seg_exporter>
4
  <reference name="content">
5
- <block type="koan_seg/adminhtml_exporter" name="exporter"/>
6
  </reference>
7
  </adminhtml_seg_exporter>
8
  </layout>
2
  <layout>
3
  <adminhtml_seg_exporter>
4
  <reference name="content">
5
+ <block type="koan_seg/adminhtml_exporter" name="exporter" />
6
  </reference>
7
  </adminhtml_seg_exporter>
8
  </layout>
package.xml CHANGED
@@ -1,41 +1,62 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>seg</name>
4
- <version>1.0.0.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
  <channel>community</channel>
8
  <extends/>
9
- <summary>Easily and automatically make more revenue from MailChimp by understanding customer preferences and behaviour.</summary>
10
- <description>Seg makes Magento and MailChimp really work together. If you run an Magento store and use MailChimp, you really need to use Seg; it will transform the effectiveness of your email marketing campaigns in MailChimp. &#xD;
11
- &#xD;
12
- = What does Seg do? = &#xD;
13
- Seg for Magento + MailChimp captures all your visitors behaviour from their email, web browsing and orders and turns that into rich profiles of their preferences for your categories &amp; products, and how likely they are to respond to emails, offers and more. &#xD;
14
- &#xD;
15
- You can then create your campaign in MailChimp as normal, but you use Seg to target the right customers for your content based on a wide range of factors including: &#xD;
16
- - How much money you want to make from your campaign (we predict that too!) &#xD;
17
- - How relevant the content is to your customers (customers who have "shown an interest" vs. "love" category/brand X) &#xD;
18
- - Whether they've bought recently &#xD;
19
- - Whether they've visited recently &#xD;
20
- - And so much more. &#xD;
21
- &#xD;
22
- You can also: &#xD;
23
- - See how much revenue and profit your MailChimp campaigns have made in detail &#xD;
24
- - See your customers in real time and what they are doing on your website &#xD;
25
- - See a detailed profile for every customer that has ever visited or bought from your store and what their preferences are &#xD;
26
- - See exactly how you can improve your email marketing (through MailChimp), inlcuding how much money you could make &#xD;
27
- - See your campaign performance over time via our email analytics system &#xD;
28
- &#xD;
29
- Seg automatically does this for you: &#xD;
30
- - Tracks all customers behaviour and orders &#xD;
31
- - Protects you from over-emailing your customers (you set the limit) &#xD;
32
- - Predicts the revenue you will make from a campaign (knowing individual customer's behaviours and preferences) so you can tailor the audience to make the most money &#xD;
33
- - Rates each campaign (as 1-5 stars) so you can easily find the best campaigns and improve them / resend them / use for inspiration in the future</description>
34
- <notes>First stable release.</notes>
35
- <authors><author><name>Seg</name><user>KoanLeeroy</user><email>Lee@koan.is</email></author></authors>
36
- <date>2015-07-31</date>
37
- <time>13:30:44</time>
38
- <contents><target name="magecommunity"><dir name="Koan"><dir name="Seg"><dir name="Block"><dir name="Adminhtml"><dir name="Exporter"><dir name="Grid"><dir name="Renderer"><file name="Status.php" hash="bab35c7c04bfb7b2ca628a08f9d0b9cf"/></dir></dir><file name="Grid.php" hash="5c4d9013851c80b14d9240e800cc5f54"/></dir><file name="Exporter.php" hash="c8ad547a58f8bd3b56d1d18627389e32"/></dir><file name="Header.php" hash="bd07e0f326730dd7ccb796eb2f33a1c7"/><file name="Track.php" hash="b04e1d5090b6c6f9e2d34a46ac31c9ae"/></dir><dir name="Helper"><file name="Data.php" hash="147ac05f825ce5dcf11f104ea629d0c4"/></dir><dir name="Model"><dir name="Batch"><file name="Status.php" hash="1eebea45e69dbf320a871ef535c49772"/></dir><dir name="Exception"><file name="Handler.php" hash="60cef7aef2b276fbd42d17f5406a4d64"/></dir><file name="Logger.php" hash="d2f267ea04603190d30dbcf185b6651f"/><file name="Observer.php" hash="faad57341c555ba99061605c0562a907"/><dir name="Resource"><dir name="Batch"><dir name="Status"><file name="Collection.php" hash="814df925981a77007df1d7710d407ec5"/></dir><file name="Status.php" hash="f96826a954f09bc9fc67e97f14dec207"/></dir></dir><dir name="Seg"><file name="Basket.php" hash="00c1c6b1ddeb5300b5d79d7793a4e7c9"/><file name="Client.php" hash="8c0563b5e1103a9b7991a13c5f8051d3"/><file name="Customer.php" hash="fc8c59e8cd5daaa7fd6a839c3be8ab11"/><file name="Exporter.php" hash="8201cddf650385f0371a41b5654a5176"/><dir name="Order"><file name="Line.php" hash="c2acaea156dcaedf8dbe50f3c98987e2"/></dir><file name="Order.php" hash="d3af49ea2c8a5c09829ff3f712c0058d"/><file name="Product.php" hash="dba1f75f98972013113392df55273922"/><dir name="Quote"><file name="Line.php" hash="352335afd649295052173e4c4d177e3c"/></dir><file name="Range.php" hash="81b1eed35211554c2a76df4160ff992a"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="SegController.php" hash="5c3fa5c56c91dff79a46fe862baf94fe"/></dir><file name="IndexController.php" hash="5d4a841c4f1bb1d3de2dfe1a325abe0f"/></dir><dir name="etc"><file name="adminhtml.xml" hash="0f44123ff295e29dc1f53967a1e5eff4"/><file name="config.xml" hash="7cca137d8acbc54de7ae46e86922aee1"/><file name="system.xml" hash="2a732cb77e3bba5d8d1d1caf8a146faf"/></dir><dir name="lib"><file name="Rollbar.php" hash="b93689fd5505f34a686cb5b979d0fdca"/></dir><dir name="sql"><dir name="koan_seg_setup"><file name="install-1.0.0.0.php" hash="983531e5fb85bdff121a5d0d74b34025"/><file name="upgrade-1.0.0.0-1.0.0.1.php" hash="9c91352527e09881251fd92766ac7a6f"/><file name="upgrade-1.0.0.1-1.0.0.2.php" hash="3a664531053ec11f56688527105cf8cd"/></dir></dir></dir><file name=".DS_Store" hash="194577a7e20bdcc7afbb718f502c134c"/></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="seg.xml" hash="4980a411970cde4aacae7d2a3c1815bb"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="seg.xml" hash="017d053269b5e2741eb58370696b1669"/></dir><dir name="template"><dir name="seg"><file name="config.phtml" hash="079d1614bcc44acc0766d9f43f5131a3"/><file name="tracking.phtml" hash="8085abd78c95b8eace352f64a07738ab"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Koan_Seg.xml" hash="7bea24d633fd1e53870ecc7fe19b4e41"/></dir></target></contents>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  <compatible/>
40
  <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
41
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>seg</name>
4
+ <version>1.1.1.0</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License (OSL 3.0)</license>
7
  <channel>community</channel>
8
  <extends/>
9
+ <summary>Seg unlocks the potential of your Magento user data to supercharge your email marketing. Install free today.</summary>
10
+ <description>Seg transforms the effectiveness of your email marketing by seamlessly integrating with and enhancing the marketing software you already use. &#xD;
11
+ &#xD;
12
+ By recording your onsite customer behaviour and looking at past order history, you can **create custom automated marketing workflows** that really work for your business. &#xD;
13
+ &#xD;
14
+ Some recommended workflows to get you started: &#xD;
15
+ - **Cart abandonment** email series &#xD;
16
+ - **Browse recovery** email series &#xD;
17
+ - **Win back customers** who haven't shopped for a while &#xD;
18
+ - **Treat your VIPs** with exclusive offers and content &#xD;
19
+ - **Email relevant content** based on behaviour, order history and shopping preferences. &#xD;
20
+ &#xD;
21
+ Send fewer, more targeted emails to maximise email conversion rates. That means, no more bulk emails with low open rates. That means, less time spent on campaign design and planning. &#xD;
22
+ &#xD;
23
+ ---------------------------------------&#xD;
24
+ &#xD;
25
+ *** Features &#xD;
26
+ &#xD;
27
+ ***** Email marketing segmentation &#xD;
28
+ Seg's rich user profiling will amaze your team and give unbelievable customer insight.&#xD;
29
+ - Seg *collects all your user* data in realtime, as they are browsing your store&#xD;
30
+ - Use *purchase and browsing behavior to build customer profiles* as well as email interaction&#xD;
31
+ - *Email your customer segments* by sending them to MailChimp with 1-click.&#xD;
32
+ - You can *import all your historical customer data* so you can start automating based on previous shopping preferences straight away.&#xD;
33
+ &#xD;
34
+ ***** Automated workflows &#xD;
35
+ Say goodbye to scheduling &#x2013; by automating most of your email marketing, you can save your team valuable time and resource, while maximising your return from email. &#xD;
36
+ - Create *custom workflows based on customer profiles* and never send an irrelevant email again&#xD;
37
+ - *Connect with over 500+ apps* you already know how to use&#xD;
38
+ - *Take any marketing action you can imagine.* Trigger emails, send SMS or even send a list of your old best customers to a google sheet so you can give them a call!&#xD;
39
+ - *Easily turn on our pre-built workflows* to start automating straight away&#xD;
40
+ - *Automate based on browsing behaviour and customer life cycles*, not just email interaction&#xD;
41
+ &#xD;
42
+ ***** Report &#xD;
43
+ Attribute individual orders to emails (or any other customer communication) easily by integrating your eCommerce and CRM systems in Seg.&#xD;
44
+ - Flexible attribution for reporting that matches with your other systems and works for your business&#xD;
45
+ - Find out which products you sold against campaigns and customers&#xD;
46
+ - Measure the metrics that matter to you. Whether it&#x2019;s engagement rates or revenue and profit generated, easily generate reports that get to the heart of your business&#x2019; goals.&#xD;
47
+ &#xD;
48
+ ---------------------------------------&#xD;
49
+ &#xD;
50
+ *** It's good to talk &#xD;
51
+ If you have any questions about the app, we&#x2019;re here to help. Just pop us an email at [hello@getseg.com](hello@getseg.com)&#xD;
52
+ &#xD;
53
+ *** Pricing &#xD;
54
+ We offer transparent pricing for our plans and no expensive onboarding. There are two plans,: Segment and Automate. [Find out more here](https://getseg.com/pricing).</description>
55
+ <notes>Updates to AddedToBasket event capture, tag management, order status management, multiple store-front capability and improved historical data export to Seg.</notes>
56
+ <authors><author><name>Seg</name><user>KoanLeeroy</user><email>lee@koan.is</email></author></authors>
57
+ <date>2016-07-20</date>
58
+ <time>05:18:32</time>
59
+ <contents><target name="magecommunity"><dir name="Koan"><dir name="Seg"><dir name="Block"><dir name="Adminhtml"><dir name="Exporter"><dir name="Grid"><dir name="Renderer"><file name="Log.php" hash="4d7cd9a075b1f51e82240a30c425d56a"/><file name="Status.php" hash="662e8eb5ccf2e024fe8701bd10b3a753"/></dir></dir><file name="Grid.php" hash="2035116d9a36d6e93968c89a7ded5b32"/></dir><file name="Exporter.php" hash="af0a72525d29259cd8515a7e8a8c191a"/></dir><file name="Header.php" hash="c357a4ece83409cf9580518bc575370d"/><file name="Track.php" hash="69de03202dfbbec695fc8165472c75ba"/></dir><dir name="Helper"><file name="Data.php" hash="0518977464c828685727e69e1301e863"/></dir><dir name="Model"><dir name="Batch"><file name="Log.php" hash="8596e366b2a11a8f4b3ed378c9ab767b"/><file name="Status.php" hash="259dbf63858d9586ec2db8d4bcc18b9b"/></dir><dir name="Config"><dir name="Source"><file name="Websites.php" hash="dfcf07b5a2138d3450e529c978f081bf"/></dir></dir><dir name="Exception"><file name="Handler.php" hash="60cef7aef2b276fbd42d17f5406a4d64"/></dir><dir name="Guid"><file name="Validator.php" hash="34a60bcd3613c3e395eff37b324965f8"/></dir><file name="Logger.php" hash="d2f267ea04603190d30dbcf185b6651f"/><file name="Observer.php" hash="10c3893b5b89ff6be324c2224db12ee4"/><dir name="Resource"><dir name="Batch"><dir name="Log"><file name="Collection.php" hash="bfe3d12a5374e97bc2e7afdb80634733"/></dir><file name="Log.php" hash="4e981896908e00032dab327a4e876610"/><dir name="Status"><file name="Collection.php" hash="814df925981a77007df1d7710d407ec5"/></dir><file name="Status.php" hash="f96826a954f09bc9fc67e97f14dec207"/></dir><dir name="Log"><dir name="Status"><file name="Collection.php" hash="814df925981a77007df1d7710d407ec5"/></dir><file name="Status.php" hash="f96826a954f09bc9fc67e97f14dec207"/></dir></dir><dir name="Seg"><file name="Basket.php" hash="2685a1fc7ea6dce89ec37800db177f42"/><file name="Client.php" hash="c686f1140b258bd83a3ec49ee61a4262"/><file name="Customer.php" hash="fc8c59e8cd5daaa7fd6a839c3be8ab11"/><file name="Exporter.php" hash="a6ef31b18ffeff8450edad41d005b39f"/><dir name="Order"><file name="Line.php" hash="e7f913457abda73772f0b5189a09265b"/></dir><file name="Order.php" hash="d3af49ea2c8a5c09829ff3f712c0058d"/><file name="Product.php" hash="2747dc540876074d9cd0069709bd436c"/><dir name="Quote"><file name="Line.php" hash="64acdef420ae4a94f154c3cfc2c03f3a"/></dir><file name="Range.php" hash="fa3ac1a7c62887c2ad196bb1579235c5"/></dir><dir name="Singlepayload"><file name="Exception.php" hash="4fb177b69115d9407dc3d28888c0881e"/></dir><dir name="System"><dir name="Config"><dir name="Source"><file name="Attributes.php" hash="57c2420a0f221f8265adc9203529d0c0"/></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="SegController.php" hash="93bfb99dbac7fae552c3469b01ed8748"/></dir><file name="IndexController.php" hash="5d4a841c4f1bb1d3de2dfe1a325abe0f"/></dir><dir name="etc"><file name="adminhtml.xml" hash="e3f0a996769ab63bedad8294b252dda4"/><file name="config.xml" hash="2f881bb8b983440c803d71ba32033fe6"/><file name="system.xml" hash="b47c423548f3c9b18962d97598087d35"/></dir><dir name="lib"><file name="Rollbar.php" hash="b93689fd5505f34a686cb5b979d0fdca"/></dir><dir name="sql"><dir name="koan_seg_setup"><file name="install-1.0.0.0.php" hash="983531e5fb85bdff121a5d0d74b34025"/><file name="upgrade-1.0.0.0-1.0.0.1.php" hash="7319d9d9ef61e5705d04dc3bf8eea136"/><file name="upgrade-1.0.0.1-1.0.0.2.php" hash="a4cb573c73b2ed36f41eded6f1398b69"/><file name="upgrade-1.0.0.2-1.0.0.3.php" hash="42b2e8713d49320b68d83411a9263e6c"/><file name="upgrade-1.0.0.3-1.0.0.4.php" hash="1ed6cb246727e5b9eae326a9d0082e93"/><file name="upgrade-1.0.0.4-1.0.0.5.php" hash="025839fb7bf0c093149fab18c56211a3"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="seg.xml" hash="27fe042622d312082f8af11ddcf0d35b"/></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="seg.xml" hash="017d053269b5e2741eb58370696b1669"/></dir><dir name="template"><dir name="seg"><file name="config.phtml" hash="079d1614bcc44acc0766d9f43f5131a3"/><file name="tracking.phtml" hash="8085abd78c95b8eace352f64a07738ab"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Koan_Seg.xml" hash="7bea24d633fd1e53870ecc7fe19b4e41"/></dir></target></contents>
60
  <compatible/>
61
  <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
62
  </package>