Auctane_ShipStation - Version 1.3.24

Version Notes

Official release.



Compatibility with php running as cgi, allows exporting base or store price.

Download this release

Release Info

Developer Classy Llama
Extension Auctane_ShipStation
Version 1.3.24
Comparing to
See all releases


Code changes from version 1.3.23 to 1.3.24

app/code/community/Auctane/Api/Helper/Data.php CHANGED
@@ -1,4 +1,5 @@
1
  <?php
 
2
  /**
3
  * ShipStation
4
  *
@@ -16,57 +17,55 @@
16
  * @package Auctane_Api
17
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
18
  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- class Auctane_Api_Helper_Data extends Mage_Core_Helper_Data
21
- {
22
-
23
- private $_strBundleSku = '';
24
-
25
- /**
26
- * Write a source object to an XML stream, mapping fields via a fieldset.
27
- * Fieldsets are nodes in config.xml
28
- *
29
- * @param string $fieldset
30
- * @param array|Varien_Object $source
31
- * @param XMLWriter $xml
32
- */
33
- public function fieldsetToXml($fieldset, $source, XMLWriter $xml, $isBundle = 0)
34
- {
35
- $fields = (array) Mage::getConfig()->getFieldset($fieldset);
36
- $intImportChildProducts = Mage::getStoreConfig('auctaneapi/general/import_child_products');
37
- foreach ($fields as $field => $dest) {
38
- if (!$dest->auctaneapi) continue;
39
-
40
- $name = $dest->auctaneapi == '*' ? $field : $dest->auctaneapi;
41
- $value = $source instanceof Varien_Object
42
- ? $source->getDataUsingMethod($field)
43
- : @$source[$field];
44
-
45
- if($isBundle == 1 && $name == 'UnitPrice' && $intImportChildProducts == 1) {
46
- //continue;
47
- $value = 0;
48
- }
49
-
50
-
51
- $xml->startElement((string) $name);
52
- if (is_numeric($value)) {
53
- $xml->text((string) $value);
54
- }
55
- elseif ($value) {
56
- $xml->writeCdata((string) $value);
57
- }
58
- $xml->endElement();
59
- }
60
- }
61
-
62
  /**
63
  * Write discounts info to order
64
  * @param array $discount
65
  * @param XMLWriter $xml
66
  */
67
- public function writeDiscountsInfo(array $discounts, XMLWriter $xml)
68
- {
69
- foreach ($discounts as $rule => $total) {
70
  $salesRule = Mage::getModel('salesrule/rule')->load($rule);
71
 
72
  if (!$salesRule->getId()) {
@@ -74,92 +73,87 @@ class Auctane_Api_Helper_Data extends Mage_Core_Helper_Data
74
  }
75
 
76
  $xml->startElement('Item');
77
-
78
- $xml->startElement('SKU');
79
- $xml->writeCdata($salesRule->getCouponCode() ? $salesRule->getCouponCode() : 'AUTOMATIC_DISCOUNT');
80
  $xml->endElement();
81
- $xml->startElement('Name');
82
- $xml->writeCdata($salesRule->getName());
83
  $xml->endElement();
84
- $xml->startElement('Adjustment');
85
- $xml->writeCdata('true');
86
- $xml->endElement();
87
- $xml->startElement('Quantity');
88
- $xml->text(1);
89
  $xml->endElement();
90
- $xml->startElement('UnitPrice');
91
- $xml->text(-$total);
92
  $xml->endElement();
93
-
 
 
 
94
  $xml->endElement();
95
  }
96
  }
97
-
98
  /**
99
  * Write purchase order info to order
100
  * @param Mage_Sales_Model_Order $order
101
  * @param XMLWriter $xml
102
- */
103
- public function writePoNumber($order, $xml)
104
- {
105
- $payment = $order->getPayment();
106
- $xml->startElement('PO');
107
- if($payment) {
108
- $xml->writeCdata($payment->getPoNumber());
109
  }
110
- $xml->endElement();
111
  }
112
-
113
- /**
114
- * @return array of string names
115
- * @see "auctane_exclude" nodes in config.xml
116
- */
117
- public function getIncludedProductTypes()
118
- {
119
- static $types;
120
- if (!isset($types)) {
121
- $types = Mage::getModel('catalog/product_type')->getTypes();
122
- $types = array_filter($types, create_function('$type', 'return !@$type["auctane_exclude"];'));
123
- }
124
- return array_keys($types);
125
- }
126
-
127
- /**
128
- * Indicate if a {$type} is specifically excluded by config
129
- *
130
- * @param string $type
131
- * @return bool
132
- */
133
- public function isExcludedProductType($type)
134
- {
135
- static $types;
136
- if (!isset($types)) {
137
- $types = Mage::getModel('catalog/product_type')->getTypes();
138
- $types = array_filter($types, create_function('$type', 'return (bool) @$type["auctane_exclude"];'));
139
- }
140
- return isset($types[$type]);
141
- }
142
-
143
- /**
144
- * A simple list of module names for debugging.
145
- *
146
- * @return string
147
- */
148
- public function getModuleList()
149
- {
150
- $modules = array_keys((array)Mage::getConfig()->getNode('modules')->children());
151
- return implode(',', $modules);
152
- }
153
-
154
  /**
155
  * Get export price type
156
  *
157
  * @param int $store
158
  * @return int
159
- */
160
- public function getExportPriceType($store)
161
- {
162
- return Mage::getStoreConfig('auctaneapi/general/export_price', $store);
163
  }
164
 
165
  /**
@@ -167,28 +161,26 @@ class Auctane_Api_Helper_Data extends Mage_Core_Helper_Data
167
  *
168
  * @param int $bundleProductId
169
  * @return array()
170
- */
171
- public function getBundleItems($bundleProductId){
172
- try{
173
-
174
- $bundledProduct = new Mage_Catalog_Model_Product();
175
- $bundledProduct->load($bundleProductId);
176
- $selectionCollection = $bundledProduct->getTypeInstance(true)->getSelectionsCollection(
177
- $bundledProduct->getTypeInstance(true)->getOptionsIds($bundledProduct), $bundledProduct
178
- );
179
- $bundleItems = array();
180
- foreach($selectionCollection as $option)
181
- {
182
- // Assign bundle product items to global array.
183
- $bundleItems[] = $option->product_id;
184
- }
185
-
186
- return $bundleItems;
187
-
188
- }catch(Exception $e){
189
- Mage::log($e->getMessage());
190
- return array();
191
- }
192
- }
193
 
194
  }
1
  <?php
2
+
3
  /**
4
  * ShipStation
5
  *
17
  * @package Auctane_Api
18
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
19
  */
20
+ class Auctane_Api_Helper_Data extends Mage_Core_Helper_Data {
21
+
22
+ private $_strBundleSku = '';
23
+
24
+ /**
25
+ * Write a source object to an XML stream, mapping fields via a fieldset.
26
+ * Fieldsets are nodes in config.xml
27
+ *
28
+ * @param string $fieldset
29
+ * @param array|Varien_Object $source
30
+ * @param XMLWriter $xml
31
+ */
32
+ public function fieldsetToXml($fieldset, $source, XMLWriter $xml, $isBundle = 0, $fltConfigItemPrice = 0) {
33
+ $fields = (array) Mage::getConfig()->getFieldset($fieldset);
34
+ //Check for the importing the child product settings
35
+ $intImportChildProducts = Mage::getStoreConfig('auctaneapi/general/import_child_products');
36
+ foreach ($fields as $field => $dest) {
37
+ if (!$dest->auctaneapi)
38
+ continue;
39
+
40
+ $name = $dest->auctaneapi == '*' ? $field : $dest->auctaneapi;
41
+ $value = $source instanceof Varien_Object ? $source->getDataUsingMethod($field) : @$source[$field];
42
+ //Set the child item price of bundle products to 0
43
+ if ($isBundle == 1 && $name == 'UnitPrice' && $intImportChildProducts == 1) {
44
+ //continue;
45
+ $value = 0;
46
+ }
47
+ //set the configurable product base price
48
+ if ($name == 'UnitPrice' && $fltConfigItemPrice) {
49
+ $value = $fltConfigItemPrice;
50
+ }
51
+
52
+ $xml->startElement((string) $name);
53
+ if (is_numeric($value)) {
54
+ $xml->text((string) $value);
55
+ } elseif ($value) {
56
+ $xml->writeCdata((string) $value);
57
+ }
58
+ $xml->endElement();
59
+ }
60
+ }
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  /**
63
  * Write discounts info to order
64
  * @param array $discount
65
  * @param XMLWriter $xml
66
  */
67
+ public function writeDiscountsInfo(array $discounts, XMLWriter $xml) {
68
+ foreach ($discounts as $rule => $total) {
 
69
  $salesRule = Mage::getModel('salesrule/rule')->load($rule);
70
 
71
  if (!$salesRule->getId()) {
73
  }
74
 
75
  $xml->startElement('Item');
76
+
77
+ $xml->startElement('SKU');
78
+ $xml->writeCdata($salesRule->getCouponCode() ? $salesRule->getCouponCode() : 'AUTOMATIC_DISCOUNT');
79
  $xml->endElement();
80
+ $xml->startElement('Name');
81
+ $xml->writeCdata($salesRule->getName());
82
  $xml->endElement();
83
+ $xml->startElement('Adjustment');
84
+ $xml->writeCdata('true');
 
 
 
85
  $xml->endElement();
86
+ $xml->startElement('Quantity');
87
+ $xml->text(1);
88
  $xml->endElement();
89
+ $xml->startElement('UnitPrice');
90
+ $xml->text(-$total);
91
+ $xml->endElement();
92
+
93
  $xml->endElement();
94
  }
95
  }
96
+
97
  /**
98
  * Write purchase order info to order
99
  * @param Mage_Sales_Model_Order $order
100
  * @param XMLWriter $xml
101
+ */
102
+ public function writePoNumber($order, $xml) {
103
+ $payment = $order->getPayment();
104
+ $xml->startElement('PO');
105
+ if ($payment) {
106
+ $xml->writeCdata($payment->getPoNumber());
 
107
  }
108
+ $xml->endElement();
109
  }
110
+
111
+ /**
112
+ * @return array of string names
113
+ * @see "auctane_exclude" nodes in config.xml
114
+ */
115
+ public function getIncludedProductTypes() {
116
+ static $types;
117
+ if (!isset($types)) {
118
+ $types = Mage::getModel('catalog/product_type')->getTypes();
119
+ $types = array_filter($types, create_function('$type', 'return !@$type["auctane_exclude"];'));
120
+ }
121
+ return array_keys($types);
122
+ }
123
+
124
+ /**
125
+ * Indicate if a {$type} is specifically excluded by config
126
+ *
127
+ * @param string $type
128
+ * @return bool
129
+ */
130
+ public function isExcludedProductType($type) {
131
+ static $types;
132
+ if (!isset($types)) {
133
+ $types = Mage::getModel('catalog/product_type')->getTypes();
134
+ $types = array_filter($types, create_function('$type', 'return (bool) @$type["auctane_exclude"];'));
135
+ }
136
+ return isset($types[$type]);
137
+ }
138
+
139
+ /**
140
+ * A simple list of module names for debugging.
141
+ *
142
+ * @return string
143
+ */
144
+ public function getModuleList() {
145
+ $modules = array_keys((array) Mage::getConfig()->getNode('modules')->children());
146
+ return implode(',', $modules);
147
+ }
148
+
 
 
 
149
  /**
150
  * Get export price type
151
  *
152
  * @param int $store
153
  * @return int
154
+ */
155
+ public function getExportPriceType($store) {
156
+ return Mage::getStoreConfig('auctaneapi/general/export_price', $store);
 
157
  }
158
 
159
  /**
161
  *
162
  * @param int $bundleProductId
163
  * @return array()
164
+ */
165
+ public function getBundleItems($bundleProductId) {
166
+ try {
167
+
168
+ $bundledProduct = new Mage_Catalog_Model_Product();
169
+ $bundledProduct->load($bundleProductId);
170
+ $selectionCollection = $bundledProduct->getTypeInstance(true)->getSelectionsCollection(
171
+ $bundledProduct->getTypeInstance(true)->getOptionsIds($bundledProduct), $bundledProduct
172
+ );
173
+ $bundleItems = array();
174
+ foreach ($selectionCollection as $option) {
175
+ // Assign bundle product items to global array.
176
+ $bundleItems[] = $option->product_id;
177
+ }
178
+
179
+ return $bundleItems;
180
+ } catch (Exception $e) {
181
+ Mage::log($e->getMessage());
182
+ return array();
183
+ }
184
+ }
 
 
185
 
186
  }
app/code/community/Auctane/Api/Model/Action/Export.php CHANGED
@@ -2,358 +2,345 @@
2
 
3
  class Auctane_Api_Model_Action_Export {
4
 
5
- /**
6
- * Perform an export according to the given request.
7
- *
8
- * @param Mage_Core_Controller_Request_Http $request
9
- * @param Mage_Core_Controller_Response_Http $response
10
- * @throws Exception
11
- */
12
- public function process(Mage_Core_Controller_Request_Http $request,
13
- Mage_Core_Controller_Response_Http $response)
14
- {
15
- // In case store is part of URL path use it to choose config.
16
- $store = $request->get('store');
17
- if ($store) $store = Mage::app()->getStore($store);
18
-
19
- $apiConfigCharset = Mage::getStoreConfig("api/config/charset", $store);
20
-
21
- $start_date = strtotime($request->getParam('start_date'));
22
- $end_date = strtotime($request->getParam('end_date'));
23
- if (!$start_date || !$end_date) throw new Exception('Start and end dates are required', 400);
24
-
25
- $page = (int) $request->getParam('page');
26
-
27
- /* @var $orders Mage_Sales_Model_Mysql4_Order_Collection */
28
- $orders = Mage::getResourceModel('sales/order_collection');
29
- // might use 'created_at' attribute instead
30
- $orders->addAttributeToFilter('updated_at',
31
- array(
32
- 'from' => date('Y-m-d H:i:s', $start_date),
33
- 'to' => date('Y-m-d H:i:s', $end_date)
34
- ));
35
- if ($store) $orders->addAttributeToFilter('store_id', $store->getId());
36
- if ($page > 0) $orders->setPage($page, $this->_getExportPageSize());
37
-
38
- $xml = new XMLWriter;
39
- $xml->openMemory();
40
- $xml->startDocument('1.0', $apiConfigCharset);
41
- $this->_writeOrders($orders, $xml, $store ? $store->getId() : 0);
42
- $xml->endDocument();
43
-
44
- $response->clearHeaders()
45
- ->setHeader('Content-Type','text/xml; charset='.$apiConfigCharset)
46
- ->setBody($xml->outputMemory(true));
47
- }
48
-
49
- protected function _getExportPageSize()
50
- {
51
- return (int) Mage::getStoreConfig('auctaneapi/config/exportPageSize');
52
- }
53
-
54
- protected function _writeOrders(Varien_Data_Collection $orders, XMLWriter $xml, $storeId = null)
55
- {
56
- $xml->startElement('Orders');
57
- $xml->writeAttribute('pages', $orders->getLastPageNumber());
58
- foreach ($orders as $order) {
59
- $this->_writeOrder($order, $xml, $storeId);
60
- }
61
- $xml->startElement('Query');
62
- $xml->writeCdata($orders->getSelectSql());
63
- $xml->endElement(); // Query
64
-
65
- $xml->startElement('Version');
66
- $xml->writeCdata('Magento ' . Mage::getVersion());
67
- $xml->endElement(); // Version
68
-
69
- $xml->startElement('Extensions');
70
- $xml->writeCdata(Mage::helper('auctaneapi')->getModuleList());
71
- $xml->endElement(); // Extensions
72
-
73
- $xml->endElement(); // Orders
74
- }
75
-
76
- protected function _writeOrder(Mage_Sales_Model_Order $order, XMLWriter $xml, $storeId = null)
77
- {
78
- $history = '';
79
- /* @var $status Mage_Sales_Model_Order_Status */
80
- foreach ($order->getStatusHistoryCollection() as $status) {
81
- if ($status->getComment()) {
82
- $history .= $status->getCreatedAt() . PHP_EOL;
83
- $history .= $status->getComment() . PHP_EOL . PHP_EOL;
84
- }
85
- }
86
- $history = trim($history);
87
- if ($history) {
88
- $order->setStatusHistoryText($history);
89
- }
90
-
91
- /* @var $gift Mage_GiftMessage_Model_Message */
92
- $gift = Mage::helper('giftmessage/message')->getGiftMessage($order->getGiftMessageId());
93
- $order->setGift($gift->isObjectNew() ? 'false' : 'true');
94
- if (!$gift->isObjectNew()) {
95
- $order->setGiftMessage(sprintf("From: %s\nTo: %s\nMessage: %s",
96
- $gift->getSender(), $gift->getRecipient(), $gift->getMessage()));
97
- }
98
-
99
- $helper = Mage::helper('auctaneapi');
100
-
101
- $xml->startElement('Order');
102
-
103
- if($helper->getExportPriceType($order->getStoreId()) == Auctane_Api_Model_System_Source_Config_Prices::BASE_PRICE) {
104
  $helper->fieldsetToXml('base_sales_order', $order, $xml);
105
  } else {
106
- $helper->fieldsetToXml('sales_order', $order, $xml);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
-
109
- $xml->startElement('Customer');
110
- $xml->startElement('CustomerCode');
111
- $xml->writeCdata($order->getCustomerEmail());
112
- $xml->endElement(); // CustomerCode
113
-
114
- $xml->startElement('BillTo');
115
- $helper->fieldsetToXml('sales_order_billing_address',
116
- $order->getBillingAddress(), $xml);
117
- $xml->endElement(); // BillTo
118
-
119
- $xml->startElement('ShipTo');
120
- $helper->fieldsetToXml('sales_order_shipping_address',
121
- $order->getShippingAddress(), $xml);
122
- $xml->endElement(); // ShipTo
123
-
124
- $xml->endElement(); // Customer
125
-
126
- /** add purchase order nubmer */
127
- Mage::helper('auctaneapi')->writePoNumber($order, $xml);
128
-
129
- $xml->startElement('Items');
130
- /* @var $item Mage_Sales_Model_Order_Item */
131
- $bundleItems = array();
132
- $orderItems = array();
133
- $intCnt = 0;
134
- //Check for the bundle child product to import
135
- $intImportChildProducts = Mage::getStoreConfig('auctaneapi/general/import_child_products');
136
- foreach ($order->getItemsCollection($helper->getIncludedProductTypes()) as $item) {
137
- /* @var $product Mage_Catalog_Model_Product */
138
- $product = Mage::getModel('catalog/product')
139
- ->setStoreId($storeId)
140
- ->load($item->getProductId());
141
- $productId = $product->getId();
142
-
143
- $boolIsBundleProduct = false;
144
- if($product->getTypeId() === 'bundle'){
145
- //Get all bundle items of this bundle product
146
- $bundleItems = array_flip(Mage::helper('auctaneapi')->getBundleItems($productId));
147
- $boolIsBundleProduct = true;
148
- }
149
- if($intImportChildProducts == 2 && $item->getParentItemId()){
150
- continue;
151
- }
152
-
153
- if(isset($bundleItems[$productId])) {
154
- //Remove item from bundle product items
155
- unset($bundleItems[ $productId ]);
156
- $orderItems[$intCnt]['item'] = $item;
157
- $orderItems[$intCnt]['bundle'] = 1;
158
- }else{
159
- //These are items for next processing
160
- $orderItems[$intCnt]['item'] = $item;
161
- $orderItems[$intCnt]['bundle'] = 0;
162
-
163
- if($boolIsBundleProduct == true){
164
- $orderItems[$intCnt]['bundle'] = 2;
165
- }
166
- }
167
- $intCnt++;
168
- }
169
-
170
- foreach ($orderItems as $key=>$item) {
171
- $this->_writeOrderItem($item['item'], $xml, $storeId, $item['bundle']);
172
- }
173
-
174
- $intImportDiscount = Mage::getStoreConfig('auctaneapi/general/import_discounts');
175
-
176
- if($intImportDiscount == 1){ // Import Discount is true
177
- $discounts = array();
178
- if($order->getData('auctaneapi_discounts')) {
179
- $discounts = @unserialize($order->getData('auctaneapi_discounts'));
180
- if(is_array($discounts)) {
181
- $aggregated = array();
182
- foreach($discounts as $key => $discount) {
183
- $keyData = explode('-', $key);
184
- if(isset($aggregated[$keyData[0]])) {
185
- $aggregated[$keyData[0]] += $discount;
186
- }
187
- else {
188
- $aggregated[$keyData[0]] = $discount;
189
- }
190
- }
191
- Mage::helper('auctaneapi')->writeDiscountsInfo($aggregated, $xml);
192
- }
193
- }
194
- }
195
-
196
- $xml->endElement(); // Items
197
-
198
- $xml->endElement(); // Order
199
- }
200
-
201
- protected function _writeOrderItem(Mage_Sales_Model_Order_Item $item, XMLWriter $xml, $storeId = null, $isBundle = 0)
202
- {
203
- // inherit some attributes from parent order item
204
- if ($item->getParentItemId() && !$item->getParentItem()) {
205
- $item->setParentItem(Mage::getModel('sales/order_item')->load($item->getParentItemId()));
206
- }
207
- // only inherit if parent has been hidden
208
- if ($item->getParentItem() && ($item->getPrice() == 0.000)
209
- && (Mage::helper('auctaneapi')->isExcludedProductType($item->getParentItem()->getProductType())))
210
- {
211
- $item->setPrice($item->getParentItem()->getPrice());
212
- }
213
-
214
- /* @var $gift Mage_GiftMessage_Model_Message */
215
- $gift = Mage::helper('giftmessage/message')->getGiftMessage(
216
- !$item->getGiftMessageId() && $item->getParentItem()
217
- ? $item->getParentItem()->getGiftMessageId()
218
- : $item->getGiftMessageId());
219
- $item->setGift($gift->isObjectNew() ? 'false' : 'true');
220
- if (!$gift->isObjectNew()) {
221
- $item->setGiftMessage(sprintf("From: %s\nTo: %s\nMessage: %s",
222
- $gift->getSender(), $gift->getRecipient(), $gift->getMessage()));
223
- }
224
-
225
- /* @var $product Mage_Catalog_Model_Product */
226
- $product = Mage::getModel('catalog/product')
227
- ->setStoreId($storeId)
228
- ->load($item->getProductId());
229
- // inherit some attributes from parent product item
230
- if (($parentProduct = $this->_getOrderItemParentProduct($item, $storeId))) {
231
- if (!$product->getImage() || ($product->getImage() == 'no_selection'))
232
- $product->setImage($parentProduct->getImage());
233
- if (!$product->getSmallImage() || ($product->getSmallImage() == 'no_selection'))
234
- $product->setSmallImage($parentProduct->getSmallImage());
235
- if (!$product->getThumbnail() || ($product->getThumbnail() == 'no_selection'))
236
- $product->setThumbnail($parentProduct->getThumbnail());
237
- }
238
-
239
-
240
- $xml->startElement('Item');
241
-
242
  $helper = Mage::helper('auctaneapi');
243
- if(Mage::helper('auctaneapi')->getExportPriceType($item->getOrder()->getStoreId()) ==
244
  Auctane_Api_Model_System_Source_Config_Prices::BASE_PRICE) {
245
- $helper->fieldsetToXml('base_sales_order_item', $item, $xml, $isBundle);
246
  } else {
247
- $helper->fieldsetToXml('sales_order_item', $item, $xml, $isBundle);
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  }
249
-
250
- /* using emulation so that product images come from the correct store */
251
- $appEmulation = Mage::getSingleton('core/app_emulation');
252
- $initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation( $product->getStoreId() );
253
- Mage::helper('auctaneapi')->fieldsetToXml('sales_order_item_product',
254
- $product, $xml);
255
- $appEmulation->stopEnvironmentEmulation( $initialEnvironmentInfo );
256
-
257
- $xml->startElement('Options');
258
- $this->_writeOrderProductAttribute($product, $xml, $storeId);
259
- // items may have several custom options chosen by customer
260
- foreach ((array) $item->getProductOptionByCode('options') as $option) {
261
- $this->_writeOrderItemOption($option, $xml, $storeId);
262
- }
263
- $buyRequest = $item->getProductOptionByCode('info_buyRequest');
264
- if ($buyRequest && @$buyRequest['super_attribute']) {
265
- // super_attribute is non-null and non-empty, there must be a Configurable involved
266
- $parentItem = $this->_getOrderItemParent($item);
267
  /* export configurable custom options as they are stored in parent */
268
- foreach ((array) $parentItem->getProductOptionByCode('options') as $option) {
269
  $this->_writeOrderItemOption($option, $xml, $storeId);
270
- }
271
- foreach ((array) $parentItem->getProductOptionByCode('attributes_info') as $option) {
272
- $this->_writeOrderItemOption($option, $xml, $storeId);
273
- }
274
- }
275
- $xml->endElement(); // Options
276
-
277
- $xml->endElement(); // Item
278
-
279
-
280
-
281
- }
282
-
283
- protected function _writeOrderProductAttribute(Mage_Catalog_Model_Product $product, XMLWriter $xml, $storeId = null)
284
- {
285
- // custom attributes are specified in Admin > Configuration > Sales > Auctane Shipstation API
286
- // static because attributes can be cached, they do not change during a request
287
- static $attrs = null;
288
- if (is_null($attrs)) {
289
- $attrs = Mage::getResourceModel('eav/entity_attribute_collection');
290
- $attrIds = explode(',', Mage::getStoreConfig('auctaneapi/general/customattributes', $storeId));
291
- $attrs->addFieldToFilter('attribute_id', $attrIds);
292
- }
293
-
294
- /* @var $attr Mage_Eav_Model_Entity_Attribute */
295
- foreach ($attrs as $attr) {
296
- if ($product->hasData($attr->getName())) {
297
- // if an attribute has options/labels
298
- if (in_array($attr->getFrontendInput(), array('select', 'multiselect'))) {
299
- $value = $product->getAttributeText($attr->getName());
300
- if (is_array($value)) $value = implode(',', $value);
301
- }
302
- // else is a static value
303
- else {
304
- $value = $product->getDataUsingMethod($attr->getName());
305
- }
306
- // fake an item option
307
- $option = array(
308
- 'value' => $value,
309
- 'label' => $attr->getFrontendLabel()
310
- );
311
- $this->_writeOrderItemOption($option, $xml, $storeId);
312
- }
313
- }
314
- }
315
-
316
- protected function _writeOrderItemOption($option, XMLWriter $xml)
317
- {
318
- $xml->startElement('Option');
319
- Mage::helper('auctaneapi')->fieldsetToXml('sales_order_item_option', $option, $xml);
320
- $xml->endElement(); // Option
321
- }
322
-
323
- /**
324
- * Safe way to lookup parent order items.
325
- *
326
- * @param Mage_Sales_Model_Order_Item $item
327
- * @return Mage_Sales_Model_Order_Item
328
- */
329
- protected function _getOrderItemParent(Mage_Sales_Model_Order_Item $item)
330
- {
331
- if ($item->getParentItem()) {
332
- return $item->getParentItem();
333
- }
334
-
335
- $parentItem = Mage::getModel('sales/order_item')
336
- ->load($item->getParentItemId());
337
- $item->setParentItem($parentItem);
338
- return $parentItem;
339
- }
340
-
341
- /**
342
- * @param Mage_Sales_Model_Order_Item $item
343
- * @param mixed $storeId
344
- * @return Mage_Catalog_Model_Product
345
- */
346
- protected function _getOrderItemParentProduct(Mage_Sales_Model_Order_Item $item, $storeId = null)
347
- {
348
- if ($item->getParentItemId()) {
349
- // cannot use getParentItem() because we stripped parents from the order
350
- $parentItem = $this->_getOrderItemParent($item);
351
- // initialise with store so that images are correct
352
- return Mage::getModel('catalog/product')
353
- ->setStoreId($storeId)
354
- ->load($parentItem->getProductId());
355
- }
356
- return null;
357
- }
358
 
359
  }
2
 
3
  class Auctane_Api_Model_Action_Export {
4
 
5
+ /**
6
+ * Perform an export according to the given request.
7
+ *
8
+ * @param Mage_Core_Controller_Request_Http $request
9
+ * @param Mage_Core_Controller_Response_Http $response
10
+ * @throws Exception
11
+ */
12
+ public function process(Mage_Core_Controller_Request_Http $request, Mage_Core_Controller_Response_Http $response) {
13
+ // In case store is part of URL path use it to choose config.
14
+ $store = $request->get('store');
15
+ if ($store)
16
+ $store = Mage::app()->getStore($store);
17
+
18
+ $apiConfigCharset = Mage::getStoreConfig("api/config/charset", $store);
19
+
20
+ $start_date = strtotime($request->getParam('start_date'));
21
+ $end_date = strtotime($request->getParam('end_date'));
22
+ if (!$start_date || !$end_date)
23
+ throw new Exception('Start and end dates are required', 400);
24
+
25
+ $page = (int) $request->getParam('page');
26
+
27
+ /* @var $orders Mage_Sales_Model_Mysql4_Order_Collection */
28
+ $orders = Mage::getResourceModel('sales/order_collection');
29
+ // might use 'created_at' attribute instead
30
+ $orders->addAttributeToFilter('updated_at', array(
31
+ 'from' => date('Y-m-d H:i:s', $start_date),
32
+ 'to' => date('Y-m-d H:i:s', $end_date)
33
+ ));
34
+ if ($store)
35
+ $orders->addAttributeToFilter('store_id', $store->getId());
36
+ if ($page > 0)
37
+ $orders->setPage($page, $this->_getExportPageSize());
38
+ $xml = new XMLWriter;
39
+ $xml->openMemory();
40
+ $xml->startDocument('1.0', $apiConfigCharset);
41
+ $this->_writeOrders($orders, $xml, $store ? $store->getId() : 0);
42
+ $xml->endDocument();
43
+
44
+ $response->clearHeaders()
45
+ ->setHeader('Content-Type', 'text/xml; charset=' . $apiConfigCharset)
46
+ ->setBody($xml->outputMemory(true));
47
+ }
48
+
49
+ protected function _getExportPageSize() {
50
+ return (int) Mage::getStoreConfig('auctaneapi/config/exportPageSize');
51
+ }
52
+
53
+ protected function _writeOrders(Varien_Data_Collection $orders, XMLWriter $xml, $storeId = null) {
54
+ $xml->startElement('Orders');
55
+ $xml->writeAttribute('pages', $orders->getLastPageNumber());
56
+ foreach ($orders as $order) {
57
+ $this->_writeOrder($order, $xml, $storeId);
58
+ }
59
+ $xml->startElement('Query');
60
+ $xml->writeCdata($orders->getSelectSql());
61
+ $xml->endElement(); // Query
62
+
63
+ $xml->startElement('Version');
64
+ $xml->writeCdata('Magento ' . Mage::getVersion());
65
+ $xml->endElement(); // Version
66
+
67
+ $xml->startElement('Extensions');
68
+ $xml->writeCdata(Mage::helper('auctaneapi')->getModuleList());
69
+ $xml->endElement(); // Extensions
70
+
71
+ $xml->endElement(); // Orders
72
+ }
73
+
74
+ protected function _writeOrder(Mage_Sales_Model_Order $order, XMLWriter $xml, $storeId = null) {
75
+ $history = '';
76
+ /* @var $status Mage_Sales_Model_Order_Status */
77
+ foreach ($order->getStatusHistoryCollection() as $status) {
78
+ if ($status->getComment()) {
79
+ $history .= $status->getCreatedAt() . PHP_EOL;
80
+ $history .= $status->getComment() . PHP_EOL . PHP_EOL;
81
+ }
82
+ }
83
+ $history = trim($history);
84
+ if ($history) {
85
+ $order->setStatusHistoryText($history);
86
+ }
87
+
88
+ /* @var $gift Mage_GiftMessage_Model_Message */
89
+ $gift = Mage::helper('giftmessage/message')->getGiftMessage($order->getGiftMessageId());
90
+ $order->setGift($gift->isObjectNew() ? 'false' : 'true');
91
+ if (!$gift->isObjectNew()) {
92
+ $order->setGiftMessage(sprintf("From: %s\nTo: %s\nMessage: %s", $gift->getSender(), $gift->getRecipient(), $gift->getMessage()));
93
+ }
94
+
95
+ $helper = Mage::helper('auctaneapi');
96
+
97
+ $xml->startElement('Order');
98
+
99
+ if ($helper->getExportPriceType($order->getStoreId()) == Auctane_Api_Model_System_Source_Config_Prices::BASE_PRICE) {
 
 
 
 
100
  $helper->fieldsetToXml('base_sales_order', $order, $xml);
101
  } else {
102
+ $helper->fieldsetToXml('sales_order', $order, $xml);
103
+ }
104
+
105
+ $xml->startElement('Customer');
106
+ $xml->startElement('CustomerCode');
107
+ $xml->writeCdata($order->getCustomerEmail());
108
+ $xml->endElement(); // CustomerCode
109
+
110
+ $xml->startElement('BillTo');
111
+ $helper->fieldsetToXml('sales_order_billing_address', $order->getBillingAddress(), $xml);
112
+ $xml->endElement(); // BillTo
113
+
114
+ $xml->startElement('ShipTo');
115
+ $helper->fieldsetToXml('sales_order_shipping_address', $order->getShippingAddress(), $xml);
116
+ $xml->endElement(); // ShipTo
117
+
118
+ $xml->endElement(); // Customer
119
+
120
+ /** add purchase order nubmer */
121
+ Mage::helper('auctaneapi')->writePoNumber($order, $xml);
122
+
123
+ $xml->startElement('Items');
124
+ /* @var $item Mage_Sales_Model_Order_Item */
125
+ $bundleItems = array();
126
+ $orderItems = array();
127
+ $intCnt = 0;
128
+ //Check for the bundle child product to import
129
+ $intImportChildProducts = Mage::getStoreConfig('auctaneapi/general/import_child_products');
130
+ foreach ($order->getItemsCollection($helper->getIncludedProductTypes()) as $item) {
131
+ /* @var $product Mage_Catalog_Model_Product */
132
+ $product = Mage::getModel('catalog/product')
133
+ ->setStoreId($storeId)
134
+ ->load($item->getProductId());
135
+ $productId = $product->getId();
136
+
137
+ $boolIsBundleProduct = false;
138
+ if ($product->getTypeId() === 'bundle') {
139
+ //Get all bundle items of this bundle product
140
+ $bundleItems = array_flip(Mage::helper('auctaneapi')->getBundleItems($productId));
141
+ $boolIsBundleProduct = true;
142
+ }
143
+ //Check for the parent bundle item type
144
+ $parentItem = $this->_getOrderItemParent($item);
145
+ if ($parentItem) {
146
+ if ($intImportChildProducts == 2 && $parentItem->getProductType() === 'bundle') {
147
+ continue;
148
+ }
149
+ }
150
+
151
+ if (isset($bundleItems[$productId])) {
152
+ //Remove item from bundle product items
153
+ unset($bundleItems[$productId]);
154
+ $orderItems[$intCnt]['item'] = $item;
155
+ $orderItems[$intCnt]['bundle'] = 1;
156
+ } else {
157
+ //These are items for next processing
158
+ $orderItems[$intCnt]['item'] = $item;
159
+ $orderItems[$intCnt]['bundle'] = 0;
160
+
161
+ if ($boolIsBundleProduct == true) {
162
+ $orderItems[$intCnt]['bundle'] = 2;
163
+ }
164
+ }
165
+ $intCnt++;
166
+ }
167
+
168
+ foreach ($orderItems as $key => $item) {
169
+ $this->_writeOrderItem($item['item'], $xml, $storeId, $item['bundle']);
170
+ }
171
+
172
+ $intImportDiscount = Mage::getStoreConfig('auctaneapi/general/import_discounts');
173
+
174
+ if ($intImportDiscount == 1) { // Import Discount is true
175
+ $discounts = array();
176
+ if ($order->getData('auctaneapi_discounts')) {
177
+ $discounts = @unserialize($order->getData('auctaneapi_discounts'));
178
+ if (is_array($discounts)) {
179
+ $aggregated = array();
180
+ foreach ($discounts as $key => $discount) {
181
+ $keyData = explode('-', $key);
182
+ if (isset($aggregated[$keyData[0]])) {
183
+ $aggregated[$keyData[0]] += $discount;
184
+ } else {
185
+ $aggregated[$keyData[0]] = $discount;
186
+ }
187
+ }
188
+ Mage::helper('auctaneapi')->writeDiscountsInfo($aggregated, $xml);
189
+ }
190
+ }
191
+ }
192
+
193
+ $xml->endElement(); // Items
194
+
195
+ $xml->endElement(); // Order
196
+ }
197
+
198
+ protected function _writeOrderItem(Mage_Sales_Model_Order_Item $item, XMLWriter $xml, $storeId = null, $isBundle = 0) {
199
+ // inherit some attributes from parent order item
200
+ if ($item->getParentItemId() && !$item->getParentItem()) {
201
+ $item->setParentItem(Mage::getModel('sales/order_item')->load($item->getParentItemId()));
202
  }
203
+ $fltConfigItemPrice = 0;
204
+ // only inherit if parent has been hidden
205
+ if ($item->getParentItem() && ($item->getPrice() == 0.000) && (Mage::helper('auctaneapi')->isExcludedProductType($item->getParentItem()->getProductType()))) {
206
+ $item->setPrice($item->getParentItem()->getPrice());
207
+ //set the base price of configurable product type
208
+ $fltConfigItemPrice = $item->getParentItem()->getPrice();
209
+ }
210
+
211
+ /* @var $gift Mage_GiftMessage_Model_Message */
212
+ $gift = Mage::helper('giftmessage/message')->getGiftMessage(
213
+ !$item->getGiftMessageId() && $item->getParentItem() ? $item->getParentItem()->getGiftMessageId() : $item->getGiftMessageId());
214
+ $item->setGift($gift->isObjectNew() ? 'false' : 'true');
215
+ if (!$gift->isObjectNew()) {
216
+ $item->setGiftMessage(sprintf("From: %s\nTo: %s\nMessage: %s", $gift->getSender(), $gift->getRecipient(), $gift->getMessage()));
217
+ }
218
+
219
+ /* @var $product Mage_Catalog_Model_Product */
220
+ $product = Mage::getModel('catalog/product')
221
+ ->setStoreId($storeId)
222
+ ->load($item->getProductId());
223
+ // inherit some attributes from parent product item
224
+ if (($parentProduct = $this->_getOrderItemParentProduct($item, $storeId))) {
225
+ if (!$product->getImage() || ($product->getImage() == 'no_selection'))
226
+ $product->setImage($parentProduct->getImage());
227
+ if (!$product->getSmallImage() || ($product->getSmallImage() == 'no_selection'))
228
+ $product->setSmallImage($parentProduct->getSmallImage());
229
+ if (!$product->getThumbnail() || ($product->getThumbnail() == 'no_selection'))
230
+ $product->setThumbnail($parentProduct->getThumbnail());
231
+ }
232
+
233
+
234
+ $xml->startElement('Item');
235
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
236
  $helper = Mage::helper('auctaneapi');
237
+ if (Mage::helper('auctaneapi')->getExportPriceType($item->getOrder()->getStoreId()) ==
238
  Auctane_Api_Model_System_Source_Config_Prices::BASE_PRICE) {
239
+ $helper->fieldsetToXml('base_sales_order_item', $item, $xml, $isBundle, $fltConfigItemPrice);
240
  } else {
241
+ $helper->fieldsetToXml('sales_order_item', $item, $xml, $isBundle);
242
+ }
243
+
244
+ /* using emulation so that product images come from the correct store */
245
+ $appEmulation = Mage::getSingleton('core/app_emulation');
246
+ $initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($product->getStoreId());
247
+ Mage::helper('auctaneapi')->fieldsetToXml('sales_order_item_product', $product, $xml);
248
+ $appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
249
+
250
+ $xml->startElement('Options');
251
+ $this->_writeOrderProductAttribute($product, $xml, $storeId);
252
+ // items may have several custom options chosen by customer
253
+ foreach ((array) $item->getProductOptionByCode('options') as $option) {
254
+ $this->_writeOrderItemOption($option, $xml, $storeId);
255
  }
256
+ $buyRequest = $item->getProductOptionByCode('info_buyRequest');
257
+ if ($buyRequest && @$buyRequest['super_attribute']) {
258
+ // super_attribute is non-null and non-empty, there must be a Configurable involved
259
+ $parentItem = $this->_getOrderItemParent($item);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  /* export configurable custom options as they are stored in parent */
261
+ foreach ((array) $parentItem->getProductOptionByCode('options') as $option) {
262
  $this->_writeOrderItemOption($option, $xml, $storeId);
263
+ }
264
+ foreach ((array) $parentItem->getProductOptionByCode('attributes_info') as $option) {
265
+ $this->_writeOrderItemOption($option, $xml, $storeId);
266
+ }
267
+ }
268
+ $xml->endElement(); // Options
269
+
270
+ $xml->endElement(); // Item
271
+ }
272
+
273
+ protected function _writeOrderProductAttribute(Mage_Catalog_Model_Product $product, XMLWriter $xml, $storeId = null) {
274
+ // custom attributes are specified in Admin > Configuration > Sales > Auctane Shipstation API
275
+ // static because attributes can be cached, they do not change during a request
276
+ static $attrs = null;
277
+ if (is_null($attrs)) {
278
+ $attrs = Mage::getResourceModel('eav/entity_attribute_collection');
279
+ $attrIds = explode(',', Mage::getStoreConfig('auctaneapi/general/customattributes', $storeId));
280
+ $attrs->addFieldToFilter('attribute_id', $attrIds);
281
+ }
282
+
283
+ /* @var $attr Mage_Eav_Model_Entity_Attribute */
284
+ foreach ($attrs as $attr) {
285
+ if ($product->hasData($attr->getName())) {
286
+ // if an attribute has options/labels
287
+ if (in_array($attr->getFrontendInput(), array('select', 'multiselect'))) {
288
+ $value = $product->getAttributeText($attr->getName());
289
+ if (is_array($value))
290
+ $value = implode(',', $value);
291
+ }
292
+ // else is a static value
293
+ else {
294
+ $value = $product->getDataUsingMethod($attr->getName());
295
+ }
296
+ // fake an item option
297
+ $option = array(
298
+ 'value' => $value,
299
+ 'label' => $attr->getFrontendLabel()
300
+ );
301
+ $this->_writeOrderItemOption($option, $xml, $storeId);
302
+ }
303
+ }
304
+ }
305
+
306
+ protected function _writeOrderItemOption($option, XMLWriter $xml) {
307
+ $xml->startElement('Option');
308
+ Mage::helper('auctaneapi')->fieldsetToXml('sales_order_item_option', $option, $xml);
309
+ $xml->endElement(); // Option
310
+ }
311
+
312
+ /**
313
+ * Safe way to lookup parent order items.
314
+ *
315
+ * @param Mage_Sales_Model_Order_Item $item
316
+ * @return Mage_Sales_Model_Order_Item
317
+ */
318
+ protected function _getOrderItemParent(Mage_Sales_Model_Order_Item $item) {
319
+ if ($item->getParentItem()) {
320
+ return $item->getParentItem();
321
+ }
322
+
323
+ $parentItem = Mage::getModel('sales/order_item')
324
+ ->load($item->getParentItemId());
325
+ $item->setParentItem($parentItem);
326
+ return $parentItem;
327
+ }
328
+
329
+ /**
330
+ * @param Mage_Sales_Model_Order_Item $item
331
+ * @param mixed $storeId
332
+ * @return Mage_Catalog_Model_Product
333
+ */
334
+ protected function _getOrderItemParentProduct(Mage_Sales_Model_Order_Item $item, $storeId = null) {
335
+ if ($item->getParentItemId()) {
336
+ // cannot use getParentItem() because we stripped parents from the order
337
+ $parentItem = $this->_getOrderItemParent($item);
338
+ // initialise with store so that images are correct
339
+ return Mage::getModel('catalog/product')
340
+ ->setStoreId($storeId)
341
+ ->load($parentItem->getProductId());
342
+ }
343
+ return null;
344
+ }
 
 
 
 
 
 
345
 
346
  }
app/code/community/Auctane/Api/Model/Action/Shipnotify.php CHANGED
@@ -2,181 +2,186 @@
2
 
3
  class Auctane_Api_Model_Action_Shipnotify {
4
 
5
- /**
6
- * Perform a notify using POSTed data.
7
- *
8
- * See Auctane API specification.
9
- *
10
- * @param Mage_Core_Controller_Request_Http $request
11
- * @throws Exception
12
- */
13
- public function process(Mage_Core_Controller_Request_Http $request)
14
- {
15
- // Raw XML is POSTed to this stream
16
- $xml = simplexml_load_file('php://input');
17
-
18
- // load some objects
19
- $order = $this->_getOrder($xml->OrderNumber);
20
- $qtys = $this->_getOrderItemQtys(@$xml->Items, $order);
21
- $shipment = $this->_getOrderShipment($order, $qtys);
22
-
23
- // this is where tracking is actually added
24
- $track = Mage::getModel('sales/order_shipment_track')
25
- ->setNumber($xml->TrackingNumber)
26
- ->setCarrierCode($xml->Carrier)
27
- ->setTitle($xml->Service);
28
- $shipment->addTrack($track);
29
-
30
- // 'NotifyCustomer' must be "true" or "yes" to trigger an email
31
- $notify = filter_var(@$xml->NotifyCustomer, FILTER_VALIDATE_BOOLEAN);
32
-
33
- $capture = filter_var($request->getParam('capture'), FILTER_VALIDATE_BOOLEAN);
34
- if ($capture && $order->canInvoice()) {
35
- $invoice = $order->prepareInvoice($qtys);
36
- $invoice->setRequestedCaptureCase($invoice->canCapture() ? 'online' : 'offline')
37
- ->register() // captures & updates order totals
38
- ->addComment($this->_getInvoiceComment(), $notify)
39
- ->sendEmail($notify); // always send to store manager, and optionally notify customer too
40
- $order->setIsInProcess(true); // updates status on save
41
- }
42
-
43
- // Internal notes are only visible to admin
44
- if (@$xml->InternalNotes) {
45
- $shipment->addComment($xml->InternalNotes);
46
- }
47
- // Customer notes have 'Visible On Frontend' set
48
- if ($notify) {
49
- // if no NotesToCustomer then comment is empty string
50
- $shipment->sendEmail(true, (string) @$xml->NotesToCustomer)
51
- ->setEmailSent(true);
52
- }
53
- if (@$xml->NotesToCustomer) {
54
- $shipment->addComment($xml->NotesToCustomer, $notify, true);
55
- }
56
-
57
- $transaction = Mage::getModel('core/resource_transaction');
58
- $transaction->addObject($shipment)
59
- ->addObject($track);
60
- if (isset($invoice)) {
61
- // order has been captured, therefore has been modified
62
- $transaction->addObject($invoice)
63
- ->addObject($order);
64
- }
65
- $transaction->save();
66
-
67
- if( $order->canInvoice() && !$order->canShip() ){ // then silently invoice if order is shipped to move status to "Complete")
68
- $invoice = $order->prepareInvoice();
69
- $invoice->setRequestedCaptureCase($invoice->canCapture() ? 'online' : 'offline')
70
- ->register() // captures & updates order totals
71
- ->addComment($this->_getInvoiceComment(), false)
72
- ->sendEmail(false); // always send to store manager, and optionally notify customer too
73
- $order->setIsInProcess(true); // updates status on save
74
-
75
- $transaction = Mage::getModel('core/resource_transaction');
76
- if (isset($invoice)) {
77
- // order has been captured, therefore has been modified
78
- $transaction->addObject($invoice)
79
- ->addObject($order);
80
- }
81
- $transaction->save();
82
- }
83
-
84
- }
85
-
86
- /**
87
- * Configurable comment, in case language needs to be changed.
88
- *
89
- * @return string
90
- */
91
- protected function _getInvoiceComment()
92
- {
93
- return Mage::getStoreConfig('auctaneapi/config/invoiceComment');
94
- }
95
-
96
- /**
97
- * @param string $carrierCode
98
- * @return Mage_Shipping_Model_Carrier_Interface
99
- */
100
- protected function _getCarrier($carrierCode)
101
- {
102
- $carrierCode = strtolower($carrierCode);
103
- $carrierModel = Mage::getStoreConfig("carriers/{$carrierCode}/model");
104
- if (!$carrierModel) throw new Exception('Invalid carrier specified.', 400);
105
- /* @var $carrier Mage_Shipping_Model_Carrier_Interface */
106
- $carrier = Mage::getModel($carrierModel);
107
- if (!$carrier) throw new Exception('Invalid carrier specified.', 400);
108
- if (!$carrier->isTrackingAvailable()) throw new Exception('Carrier does not supported tracking.', 400);
109
- return $carrier;
110
- }
111
-
112
- /**
113
- * @param string $orderIncrementId
114
- * @return Mage_Sales_Model_Order
115
- */
116
- protected function _getOrder($orderIncrementId)
117
- {
118
- $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
119
- if ($order->isObjectNew()) throw new Exception("Order '{$orderIncrementId}' does not exist", 400);
120
- return $order;
121
- }
122
-
123
- protected function _getOrderItemQtys(SimpleXMLElement $xmlItems, Mage_Sales_Model_Order $order)
124
- {
125
- $shipAll = !count((array) $xmlItems);
126
- /* @var $items Mage_Sales_Model_Mysql4_Order_Item_Collection */
127
- $items = $order->getItemsCollection();
128
- $qtys = array();
129
- $childs = array();
130
- /* @var $item Mage_Sales_Model_Order_Item */
131
- foreach ($items as $item) {
132
- /* collect all items qtys if shipall flag is true */
133
- if($shipAll) {
134
- if ($item->getParentItemId()) {
135
- $qtys[$item->getParentItemId()] = $item->getQtyOrdered();
136
- } else {
137
- $qtys[$item->getId()] = $item->getQtyOrdered();
138
- }
139
- continue;
140
- }
141
- // search for item by SKU
142
- @list($xmlItem) = $xmlItems->xpath(sprintf('//Item/SKU[text()="%s"]/..',
143
- addslashes($item->getSku())));
144
- if ($xmlItem) {
145
- // store quantity by order item ID, not by SKU
146
- $qtys[$item->getId()] = (float) $xmlItem->Quantity;
147
- }
148
- }
149
- //Add child products into the shipments
150
- $intImportChildProducts = Mage::getStoreConfig('auctaneapi/general/import_child_products');
151
- if($intImportChildProducts == 2) {
152
- $orderItems = $order->getAllItems();
153
- foreach ($orderItems as $objItem) {
154
- if($objItem->getParentItemId()) {
155
- $qtys[$objItem->getItemId()] = $qtys[$objItem->getParentItemId()];
156
- }
157
- }
158
- }
159
- return $qtys;
160
- }
161
-
162
- /**
163
- * @param Mage_Sales_ModelOrder $order
164
- * @param array $qtys
165
- * @return Mage_Sales_Model_Order_Shipment
166
- */
167
- protected function _getOrderShipment(Mage_Sales_Model_Order $order, $qtys)
168
- {
169
- $shipment = $order->prepareShipment($qtys);
170
- $shipment->register();
171
- $order->setIsInProgress(true);
172
-
173
- // shipment must have an ID before proceeding
174
- Mage::getModel('core/resource_transaction')
175
- ->addObject($shipment)
176
- ->addObject($order)
177
- ->save();
178
-
179
- return $shipment;
180
- }
181
-
182
- }
 
 
 
 
 
2
 
3
  class Auctane_Api_Model_Action_Shipnotify {
4
 
5
+ /**
6
+ * Perform a notify using POSTed data.
7
+ *
8
+ * See Auctane API specification.
9
+ *
10
+ * @param Mage_Core_Controller_Request_Http $request
11
+ * @throws Exception
12
+ */
13
+ public function process(Mage_Core_Controller_Request_Http $request) {
14
+ // Raw XML is POSTed to this stream
15
+ $xml = simplexml_load_file('php://input');
16
+
17
+ // load some objects
18
+ $order = $this->_getOrder($xml->OrderNumber);
19
+ $qtys = $this->_getOrderItemQtys(@$xml->Items, $order);
20
+ $shipment = $this->_getOrderShipment($order, $qtys);
21
+
22
+ // this is where tracking is actually added
23
+ $track = Mage::getModel('sales/order_shipment_track')
24
+ ->setNumber($xml->TrackingNumber)
25
+ ->setCarrierCode($xml->Carrier)
26
+ ->setTitle($xml->Service);
27
+ $shipment->addTrack($track);
28
+
29
+ // 'NotifyCustomer' must be "true" or "yes" to trigger an email
30
+ $notify = filter_var(@$xml->NotifyCustomer, FILTER_VALIDATE_BOOLEAN);
31
+
32
+ $capture = filter_var($request->getParam('capture'), FILTER_VALIDATE_BOOLEAN);
33
+ if ($capture && $order->canInvoice()) {
34
+ $invoice = $order->prepareInvoice($qtys);
35
+ $invoice->setRequestedCaptureCase($invoice->canCapture() ? 'online' : 'offline')
36
+ ->register() // captures & updates order totals
37
+ ->addComment($this->_getInvoiceComment(), $notify)
38
+ ->sendEmail($notify); // always send to store manager, and optionally notify customer too
39
+ $order->setIsInProcess(true); // updates status on save
40
+ }
41
+
42
+ // Internal notes are only visible to admin
43
+ if (@$xml->InternalNotes) {
44
+ $shipment->addComment($xml->InternalNotes);
45
+ }
46
+ // Customer notes have 'Visible On Frontend' set
47
+ if ($notify) {
48
+ // if no NotesToCustomer then comment is empty string
49
+ $shipment->sendEmail(true, (string) @$xml->NotesToCustomer)
50
+ ->setEmailSent(true);
51
+ }
52
+ if (@$xml->NotesToCustomer) {
53
+ $shipment->addComment($xml->NotesToCustomer, $notify, true);
54
+ }
55
+
56
+ $transaction = Mage::getModel('core/resource_transaction');
57
+ $transaction->addObject($shipment)
58
+ ->addObject($track);
59
+ if (isset($invoice)) {
60
+ // order has been captured, therefore has been modified
61
+ $transaction->addObject($invoice)
62
+ ->addObject($order);
63
+ }
64
+ $transaction->save();
65
+
66
+ if ($order->canInvoice() && !$order->canShip()) { // then silently invoice if order is shipped to move status to "Complete")
67
+ $invoice = $order->prepareInvoice();
68
+ $invoice->setRequestedCaptureCase($invoice->canCapture() ? 'online' : 'offline')
69
+ ->register() // captures & updates order totals
70
+ ->addComment($this->_getInvoiceComment(), false)
71
+ ->sendEmail(false); // always send to store manager, and optionally notify customer too
72
+ $order->setIsInProcess(true); // updates status on save
73
+
74
+ $transaction = Mage::getModel('core/resource_transaction');
75
+ if (isset($invoice)) {
76
+ // order has been captured, therefore has been modified
77
+ $transaction->addObject($invoice)
78
+ ->addObject($order);
79
+ }
80
+ $transaction->save();
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Configurable comment, in case language needs to be changed.
86
+ *
87
+ * @return string
88
+ */
89
+ protected function _getInvoiceComment() {
90
+ return Mage::getStoreConfig('auctaneapi/config/invoiceComment');
91
+ }
92
+
93
+ /**
94
+ * @param string $carrierCode
95
+ * @return Mage_Shipping_Model_Carrier_Interface
96
+ */
97
+ protected function _getCarrier($carrierCode) {
98
+ $carrierCode = strtolower($carrierCode);
99
+ $carrierModel = Mage::getStoreConfig("carriers/{$carrierCode}/model");
100
+ if (!$carrierModel)
101
+ throw new Exception('Invalid carrier specified.', 400);
102
+ /* @var $carrier Mage_Shipping_Model_Carrier_Interface */
103
+ $carrier = Mage::getModel($carrierModel);
104
+ if (!$carrier)
105
+ throw new Exception('Invalid carrier specified.', 400);
106
+ if (!$carrier->isTrackingAvailable())
107
+ throw new Exception('Carrier does not supported tracking.', 400);
108
+ return $carrier;
109
+ }
110
+
111
+ /**
112
+ * @param string $orderIncrementId
113
+ * @return Mage_Sales_Model_Order
114
+ */
115
+ protected function _getOrder($orderIncrementId) {
116
+ $order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
117
+ if ($order->isObjectNew())
118
+ throw new Exception("Order '{$orderIncrementId}' does not exist", 400);
119
+ return $order;
120
+ }
121
+
122
+ protected function _getOrderItemQtys(SimpleXMLElement $xmlItems, Mage_Sales_Model_Order $order) {
123
+ $shipAll = !count((array) $xmlItems);
124
+ /* @var $items Mage_Sales_Model_Mysql4_Order_Item_Collection */
125
+ $items = $order->getItemsCollection();
126
+ $qtys = array();
127
+ $childs = array();
128
+ /* @var $item Mage_Sales_Model_Order_Item */
129
+ foreach ($items as $item) {
130
+ /* collect all items qtys if shipall flag is true */
131
+ if ($shipAll) {
132
+ if ($item->getParentItemId()) {
133
+ $qtys[$item->getParentItemId()] = $item->getQtyOrdered();
134
+ } else {
135
+ $qtys[$item->getId()] = $item->getQtyOrdered();
136
+ }
137
+ continue;
138
+ }
139
+ // search for item by SKU
140
+ @list($xmlItem) = $xmlItems->xpath(sprintf('//Item/SKU[text()="%s"]/..', addslashes($item->getSku())));
141
+ if ($xmlItem) {
142
+ // store quantity by order item ID, not by SKU
143
+ $qtys[$item->getId()] = (float) $xmlItem->Quantity;
144
+ }
145
+ }
146
+ //Add child products into the shipments
147
+ $intImportChildProducts = Mage::getStoreConfig('auctaneapi/general/import_child_products');
148
+ if ($intImportChildProducts == 2) {
149
+ $orderItems = $order->getAllItems();
150
+ foreach ($orderItems as $objItem) {
151
+ if ($objItem->getParentItemId()) {
152
+ //set parent item if not set
153
+ if (!$objItem->getParentItem()) {
154
+ $objItem->setParentItem(Mage::getModel('sales/order_item')->load($objItem->getParentItemId()));
155
+ }
156
+ if ($objItem->getParentItem()) {
157
+ //check for the bundle product type
158
+ if ($objItem->getParentItem()->getProductType() === 'bundle') {
159
+ $qtys[$objItem->getItemId()] = $qtys[$objItem->getParentItemId()];
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ return $qtys;
166
+ }
167
+
168
+ /**
169
+ * @param Mage_Sales_ModelOrder $order
170
+ * @param array $qtys
171
+ * @return Mage_Sales_Model_Order_Shipment
172
+ */
173
+ protected function _getOrderShipment(Mage_Sales_Model_Order $order, $qtys) {
174
+ $shipment = $order->prepareShipment($qtys);
175
+ $shipment->register();
176
+ $order->setIsInProgress(true);
177
+
178
+ // shipment must have an ID before proceeding
179
+ Mage::getModel('core/resource_transaction')
180
+ ->addObject($shipment)
181
+ ->addObject($order)
182
+ ->save();
183
+
184
+ return $shipment;
185
+ }
186
+
187
+ }
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Auctane_ShipStation</name>
4
- <version>1.3.23</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
  <channel>community</channel>
@@ -12,9 +12,9 @@
12
  &amp;amp;amp;amp;amp;amp;amp;#xD;&amp;amp;amp;amp;amp;amp;#xD;&amp;amp;amp;amp;amp;#xD;&amp;amp;amp;amp;#xD;&amp;amp;amp;#xD;&amp;amp;#xD;&amp;#xD;&#xD;
13
  Compatibility with php running as cgi, allows exporting base or store price.</notes>
14
  <authors><author><name>Classy Llama</name><user>classyllama</user><email>info@classyllama.com</email></author></authors>
15
- <date>2014-07-25</date>
16
- <time>16:06:54</time>
17
- <contents><target name="mageetc"><dir name="modules"><file name="Auctane_Api.xml" hash="a27b534a3ad08732488959f8bdb72a03"/></dir></target><target name="magecommunity"><dir name="Auctane"><dir name="Api"><file name="CHANGELOG.txt" hash="ac302cdb9f343e0ec036b7a846294235"/><dir name="Helper"><file name="Data.php" hash="570b147833d151bbc42044a9ced0e05a"/></dir><file name="LICENSE.html" hash="caf0a79ffb5e4719f9f4de286f253a61"/><file name="LICENSE.txt" hash="34410d4f566fdc33f094525a2d9865fa"/><file name="LICENSE_AFL.txt" hash="0e3cb8112c018920eee7a316a2a69103"/><dir name="Model"><dir name="Action"><file name="Export.php" hash="e1b7931d98cf868d96bb311d9e6979c7"/><file name="Shipnotify.php" hash="8dbe4b62f1f60f9a49d17ba06c43eec8"/></dir><file name="Observer.php" hash="35039bba674a42171212e3a13b7800ca"/><dir name="Server"><file name="Adapter.php" hash="2439c54a7fe7bb44c93ee1e00b2e8dcf"/></dir><dir name="System"><dir name="Source"><dir name="Config"><file name="Customattributes.php" hash="a10dff7d323044151803ce2e30313615"/><file name="Import.php" hash="f7e86512477d957d2620084faab48327"/><file name="Prices.php" hash="0869f093096b4ff6d2ae24f14468d782"/></dir></dir></dir></dir><dir name="controllers"><file name="AuctaneController.php" hash="b7100ac35e0b3a5d737cde7ef96e19c0"/></dir><dir name="etc"><file name="api.xml" hash="3b6279da3c6a4e5fc71c72f1caf94ae1"/><file name="config.xml" hash="17552bc312cbd3cfb23e102b528438b6"/><file name="system.xml" hash="91b7c65f17f50a62029008e22dadc0ac"/></dir><dir name="sql"><dir name="auctaneapi_setup"><file name="mysql4-install-1.3.11.php" hash="17aa8f981f75f1e1d62e8dbdde2f950d"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="auctaneapi"><dir name="css"><file name="master.css" hash="0b35fa9797b3bd868b3725a85d4347af"/></dir><dir name="images"><file name="auctaneapi.png" hash="294d531f2f4f6dd85bdccd124a3057f6"/><file name="btn_bl.png" hash="093ac74aedfd1dd0addbfac3a19ced95"/><file name="header.png" hash="9228dfeb910aa6f3141d40966a6dba32"/><file name="tabs_span_bg.gif" hash="bcabd4fea0d67b181f21779564c2284b"/></dir></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="auctaneapi.xml" hash="a6fe62d8258e423bee3a129165c0d313"/></dir></dir></dir></dir></target></contents>
18
  <compatible/>
19
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
20
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Auctane_ShipStation</name>
4
+ <version>1.3.24</version>
5
  <stability>stable</stability>
6
  <license uri="http://opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
  <channel>community</channel>
12
  &amp;amp;amp;amp;amp;amp;amp;#xD;&amp;amp;amp;amp;amp;amp;#xD;&amp;amp;amp;amp;amp;#xD;&amp;amp;amp;amp;#xD;&amp;amp;amp;#xD;&amp;amp;#xD;&amp;#xD;&#xD;
13
  Compatibility with php running as cgi, allows exporting base or store price.</notes>
14
  <authors><author><name>Classy Llama</name><user>classyllama</user><email>info@classyllama.com</email></author></authors>
15
+ <date>2014-08-11</date>
16
+ <time>11:50:06</time>
17
+ <contents><target name="mageetc"><dir name="modules"><file name="Auctane_Api.xml" hash="a27b534a3ad08732488959f8bdb72a03"/></dir></target><target name="magecommunity"><dir name="Auctane"><dir name="Api"><file name="CHANGELOG.txt" hash="ac302cdb9f343e0ec036b7a846294235"/><dir name="Helper"><file name="Data.php" hash="09d59846badf0227c3f00b80426d4c88"/></dir><file name="LICENSE.html" hash="caf0a79ffb5e4719f9f4de286f253a61"/><file name="LICENSE.txt" hash="34410d4f566fdc33f094525a2d9865fa"/><file name="LICENSE_AFL.txt" hash="0e3cb8112c018920eee7a316a2a69103"/><dir name="Model"><dir name="Action"><file name="Export.php" hash="c1008c5dbac647e45d623935f84d3c02"/><file name="Shipnotify.php" hash="45733af4236d6b855d7db21f36d68cc1"/></dir><file name="Observer.php" hash="35039bba674a42171212e3a13b7800ca"/><dir name="Server"><file name="Adapter.php" hash="2439c54a7fe7bb44c93ee1e00b2e8dcf"/></dir><dir name="System"><dir name="Source"><dir name="Config"><file name="Customattributes.php" hash="a10dff7d323044151803ce2e30313615"/><file name="Import.php" hash="f7e86512477d957d2620084faab48327"/><file name="Prices.php" hash="0869f093096b4ff6d2ae24f14468d782"/></dir></dir></dir></dir><dir name="controllers"><file name="AuctaneController.php" hash="b7100ac35e0b3a5d737cde7ef96e19c0"/></dir><dir name="etc"><file name="api.xml" hash="3b6279da3c6a4e5fc71c72f1caf94ae1"/><file name="config.xml" hash="17552bc312cbd3cfb23e102b528438b6"/><file name="system.xml" hash="91b7c65f17f50a62029008e22dadc0ac"/></dir><dir name="sql"><dir name="auctaneapi_setup"><file name="mysql4-install-1.3.11.php" hash="17aa8f981f75f1e1d62e8dbdde2f950d"/></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="auctaneapi"><dir name="css"><file name="master.css" hash="0b35fa9797b3bd868b3725a85d4347af"/></dir><dir name="images"><file name="auctaneapi.png" hash="294d531f2f4f6dd85bdccd124a3057f6"/><file name="btn_bl.png" hash="093ac74aedfd1dd0addbfac3a19ced95"/><file name="header.png" hash="9228dfeb910aa6f3141d40966a6dba32"/><file name="tabs_span_bg.gif" hash="bcabd4fea0d67b181f21779564c2284b"/></dir></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="auctaneapi.xml" hash="a6fe62d8258e423bee3a129165c0d313"/></dir></dir></dir></dir></target></contents>
18
  <compatible/>
19
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
20
  </package>