SalesTax_Connector - Version 3.2.1

Version Notes

Simplify sales and use tax calculation, compliance, and management in the cloud!

Download this release

Release Info

Developer Ken Nunes
Extension SalesTax_Connector
Version 3.2.1
Comparing to
See all releases


Code changes from version 3.1.8 to 3.2.1

Files changed (32) hide show
  1. app/code/community/Harapartners/ConnectorHub/Block/Adminhtml/System/Config/Form/Field/Json.php +27 -18
  2. app/code/community/Harapartners/ConnectorHub/Helper/Connector/Config.php +2 -2
  3. app/code/community/Harapartners/ConnectorHub/Helper/Connector/Core.php +125 -50
  4. app/code/community/Harapartners/ConnectorHub/Model/Rewrite/Paypal/Config.php +7 -12
  5. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/All/Index.php +38 -0
  6. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/All/Index/Grid.php +124 -0
  7. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Failsafe/Index.php +32 -0
  8. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Failsafe/Index/Grid.php +50 -0
  9. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Rateverification/Index.php +32 -0
  10. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Rateverification/Index/Grid.php +62 -0
  11. app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Notification.php +44 -0
  12. app/code/community/Harapartners/SpeedTax/Helper/Connector/Data.php +31 -9
  13. app/code/community/Harapartners/SpeedTax/Helper/Connector/Speedtax.php +38 -38
  14. app/code/community/Harapartners/SpeedTax/Helper/Data.php +20 -0
  15. app/code/community/Harapartners/SpeedTax/Helper/Failsafe.php +73 -0
  16. app/code/community/Harapartners/SpeedTax/Helper/Processor.php +12 -9
  17. app/code/community/Harapartners/SpeedTax/Model/Failsafe/Calculation.php +42 -0
  18. app/code/community/Harapartners/SpeedTax/Model/Failsafe/Calculation/Rate.php +39 -0
  19. app/code/community/Harapartners/SpeedTax/Model/Failsafe/Sales/Total/Quote/Tax.php +27 -0
  20. app/code/community/Harapartners/SpeedTax/Model/Observer.php +118 -21
  21. app/code/community/Harapartners/SpeedTax/Model/Resource/Failsafe/Calculation/Rate.php +47 -0
  22. app/code/community/Harapartners/SpeedTax/Model/Resource/Failsafe/Calculation/Rate/Collection.php +20 -0
  23. app/code/community/Harapartners/SpeedTax/Model/Rewrite/Tax/Sales/Total/Quote/Tax.php +18 -4
  24. app/code/community/Harapartners/SpeedTax/controllers/Adminhtml/InvoiceController.php +80 -0
  25. app/code/community/Harapartners/SpeedTax/controllers/Adminhtml/NotificationController.php +32 -0
  26. app/code/community/Harapartners/SpeedTax/controllers/Adminhtml/System/Config/AjaxController.php +1 -1
  27. app/code/community/Harapartners/SpeedTax/etc/adminhtml.xml +71 -0
  28. app/code/community/Harapartners/SpeedTax/etc/config.xml +60 -25
  29. app/code/community/Harapartners/SpeedTax/etc/system.xml +65 -14
  30. app/code/community/Harapartners/SpeedTax/sql/speedtax_setup/mysql4-upgrade-3.0.9-3.1.0.php +31 -107
  31. app/code/community/Harapartners/SpeedTax/sql/speedtax_setup/mysql4-upgrade-3.9.9-4.0.0.php +101 -0
  32. package.xml +4 -4
app/code/community/Harapartners/ConnectorHub/Block/Adminhtml/System/Config/Form/Field/Json.php CHANGED
@@ -15,31 +15,18 @@ class Harapartners_ConnectorHub_Block_Adminhtml_System_Config_Form_Field_Json ex
15
 
16
  protected function _toHtml() {
17
  $element = $this->getData('element');
18
- $elementData = (string)$element->getValue();
19
- $jsonValidateData = json_decode(trim($element->getValue()), true);
20
- if(!$jsonValidateData){
21
- if($elementJsonConfig['structure'] == 'list'){
22
- $elementData = "[]";
23
- }else{
24
- $elementData = "{}";
25
- }
26
- }
27
-
28
- $hiddenInput = '<input type="hidden" id="'.$element->getHtmlId().'" name="'.$element->getName()
29
- .'" value="'.$element->getEscapedValue().'" '.$this->serialize($element->getHtmlAttributes()).'/>'."\n";
30
-
31
- $elementFieldConfig = $element->getFieldConfig();
32
  $elementJsonConfig = array(
33
  'structure' => (string)$elementFieldConfig->frontend_json_structure,
34
  'key_label' => (string)$elementFieldConfig->frontend_json_key_label,
35
  'value_label' => (string)$elementFieldConfig->frontend_json_value_label,
36
  );
37
- $elementJsonConfig = json_encode($elementJsonConfig);
38
-
39
-
40
 
 
 
 
41
  $htmlContent = <<< HTML_CONTENT
42
- $hiddenInput
43
  <div id="{$element->getHtmlId()}_json_config_widget" class="json_config_widget_container"></div>
44
  <script type="text/javascript">
45
  var {$element->getHtmlId()} = new JsonConfigWidget();
@@ -48,6 +35,28 @@ $hiddenInput
48
  HTML_CONTENT;
49
  return $htmlContent;
50
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
  protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element){
53
  $this->addData(array(
15
 
16
  protected function _toHtml() {
17
  $element = $this->getData('element');
18
+ $elementFieldConfig = $element->getFieldConfig();
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  $elementJsonConfig = array(
20
  'structure' => (string)$elementFieldConfig->frontend_json_structure,
21
  'key_label' => (string)$elementFieldConfig->frontend_json_key_label,
22
  'value_label' => (string)$elementFieldConfig->frontend_json_value_label,
23
  );
 
 
 
24
 
25
+ $elementData = $this->_prepareElementData($element, $elementJsonConfig);
26
+ $elementJsonConfig = json_encode($elementJsonConfig);
27
+
28
  $htmlContent = <<< HTML_CONTENT
29
+ <input type="hidden" id="{$element->getHtmlId()}" name="{$element->getName()}" value="{$element->getEscapedValue()}" {$this->serialize($element->getHtmlAttributes())}/>
30
  <div id="{$element->getHtmlId()}_json_config_widget" class="json_config_widget_container"></div>
31
  <script type="text/javascript">
32
  var {$element->getHtmlId()} = new JsonConfigWidget();
35
  HTML_CONTENT;
36
  return $htmlContent;
37
  }
38
+
39
+ protected function _prepareElementData($element){
40
+ $elementFieldConfig = $element->getFieldConfig();
41
+ $elementJsonConfig = array(
42
+ 'structure' => (string)$elementFieldConfig->frontend_json_structure,
43
+ 'key_label' => (string)$elementFieldConfig->frontend_json_key_label,
44
+ 'value_label' => (string)$elementFieldConfig->frontend_json_value_label,
45
+ );
46
+ $elementData = (string)$element->getValue();
47
+
48
+ //Try to decode to validate the data, if not validate, use empty placeholders
49
+ $jsonValidateData = json_decode(trim($element->getValue()), true);
50
+ if(!$jsonValidateData){
51
+ if(isset($elementJsonConfig['structure']) && $elementJsonConfig['structure'] == 'list'){
52
+ $elementData = "[]";
53
+ }else{
54
+ $elementData = "{}";
55
+ }
56
+ }
57
+
58
+ return $elementData;
59
+ }
60
 
61
  protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element){
62
  $this->addData(array(
app/code/community/Harapartners/ConnectorHub/Helper/Connector/Config.php CHANGED
@@ -15,7 +15,7 @@ class Harapartners_ConnectorHub_Helper_Connector_Config
15
 
16
  public function getConnectorHubRootUrl()
17
  {
18
- //return Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB) . "ConnectorHub/";
19
- return "https://connectorhub.harapartners.com/";
20
  }
 
21
  }
15
 
16
  public function getConnectorHubRootUrl()
17
  {
18
+ return "https://api.connectorsuite.com/";
 
19
  }
20
+
21
  }
app/code/community/Harapartners/ConnectorHub/Helper/Connector/Core.php CHANGED
@@ -25,70 +25,119 @@ abstract class Harapartners_ConnectorHub_Helper_Connector_Core {
25
 
26
  const DEFAULT_CURLOPT_TIMEOUT = 60;
27
 
 
 
28
  protected $_serviceType = null;
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  protected function _processRequest($request){
31
  // -------------- Prepare additional request meta -------------- //
32
- $adminEmail = "";
33
- if(!!Mage::getSingleton('admin/session')->getUser()){
34
- $adminEmail = Mage::getSingleton('admin/session')->getUser()->getEmail();
35
- }
36
- $request['meta'] = array_merge($request['meta'], array(
37
- 'service_type' => $this->getServiceType(),
38
- 'service_mode' => $this->getServiceMode(),
39
- 'auth_token' => $this->getToken('auth_token'),
40
- 'site_url' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB),
41
- 'account_name' => $adminEmail,
42
- 'platform' => 'magento',
43
- 'version' => Mage::getVersion()
44
- ));
45
 
46
- if(isset($request['data'])){
47
- $request['enc_data'] = $this->encryptRequestData($request['data']);
48
- unset($request['data']);
 
 
49
  }
50
 
 
 
 
51
  // -------------- Make request -------------- //
 
 
 
 
 
52
  $requestUrl = $this->_getConnectorHubUrl();
53
- $requestPostData = array('params' => base64_encode(json_encode($request)));
54
- $requestCh = curl_init();
55
- curl_setopt($requestCh, CURLOPT_URL, $requestUrl);
56
- curl_setopt($requestCh, CURLOPT_POST, 1);
57
- curl_setopt($requestCh, CURLOPT_POSTFIELDS, $requestPostData);
58
- curl_setopt($requestCh, CURLOPT_SSL_VERIFYPEER, $this->_getCurlSslVerifyPeer());
59
- curl_setopt($requestCh, CURLOPT_RETURNTRANSFER, 1);
60
- curl_setopt($requestCh, CURLOPT_TIMEOUT, self::DEFAULT_CURLOPT_TIMEOUT);
61
- $curlRawResponse = curl_exec($requestCh);
62
- $response = json_decode(base64_decode($curlRawResponse));
63
- curl_close($requestCh);
64
 
65
  // -------------- Process response -------------- //
66
  if(!$response){
67
- if($curlRawResponse){
68
- throw new Exception('Connector Hub: There is an error processing the request.');
69
  }
70
- throw new Exception('Connector Hub: Connection failed.');
71
  }
72
  //For now treat reauth the same as fail, the notification will prompt the admin user to update their credentials
73
  switch($response->meta->status){
74
  case self::RESPONSE_STATUS_FAIL:
75
  case self::RESPONSE_STATUS_REAUTH:
76
- throw new Exception("Connector Hub ({$this->getServiceType()}): " . $response->meta->message);
77
  break;
78
  case self::RESPONSE_STATUS_SUCCESS:
79
  break;
80
  default:
81
  break;
82
  }
83
- if(!!$response->enc_data){
84
- $dataToken = $this->getToken('data_token');
85
- $decData = Mage::helper('connectorhub/mcrypt')->init($dataToken)->decrypt(base64_decode($response->enc_data));
86
- $response->data = json_decode($decData);
 
 
 
 
 
87
  }
88
 
89
  return $response;
90
  }
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  public function authenticationRequest($credentials){
93
  //For authentication request, directly send the data, rather than encrypted data with token
94
  $request = array(
@@ -101,16 +150,20 @@ abstract class Harapartners_ConnectorHub_Helper_Connector_Core {
101
 
102
  //service_mode can be '0'
103
  if(is_null($response->meta->service_mode) || !$response->meta->auth_token || !$response->meta->data_token){
104
- throw new Exception("Connector Hub ({$this->getServiceType()}): Authentication failed.");
105
  }
106
 
107
- $this->saveTokens($response);
108
  return $response;
109
  }
110
 
111
 
112
  // ======================= Essential overrides ======================= //
113
- abstract public function getServiceMode();
 
 
 
 
114
 
115
  abstract protected function _getConnectorHubUrl();
116
 
@@ -124,11 +177,16 @@ abstract class Harapartners_ConnectorHub_Helper_Connector_Core {
124
  return $this->_serviceType;
125
  }
126
 
127
- public function getToken($tokenName, $serviceMode = null){
128
- if(!$serviceMode){
129
- $serviceMode = $this->getServiceMode();
130
- }
131
-
 
 
 
 
 
132
  //Load from DB, no cache
133
  $coreConfigData = Mage::getModel('core/config_data')->load($this->_getConfigDataBasePath('tokens'), 'path');
134
  $existingToken = json_decode($coreConfigData->getValue(), 1);
@@ -138,11 +196,13 @@ abstract class Harapartners_ConnectorHub_Helper_Connector_Core {
138
  return null;
139
  }
140
 
141
- public function saveTokens($response){
142
  //Save to DB, no cache
143
  $coreConfigData = Mage::getModel('core/config_data')->load($this->_getConfigDataBasePath('tokens'), 'path');
144
- //In case the first time save
145
- $coreConfigData->setpath($this->_getConfigDataBasePath('tokens'));
 
 
146
 
147
  $existingToken = json_decode($coreConfigData->getValue(), 1);
148
  $existingToken[$response->meta->service_mode] = array(
@@ -154,13 +214,15 @@ abstract class Harapartners_ConnectorHub_Helper_Connector_Core {
154
  return;
155
  }
156
 
157
- public function encryptRequestData($requestData){
158
- //For authentication request, directly send the data, rather than encrypted data with token
159
- $authToken = $this->getToken('auth_token');
160
- $dataToken = $this->getToken('data_token');
161
  $encData = Mage::helper('connectorhub/mcrypt')->init($dataToken)->encrypt(json_encode($requestData));
162
  return base64_encode($encData);
163
  }
 
 
 
 
 
164
 
165
  protected function _getCurlSslVerifyPeer(){
166
  $sslVerifyPeer = 0;
@@ -178,5 +240,18 @@ abstract class Harapartners_ConnectorHub_Helper_Connector_Core {
178
  protected function _getConnectorHubRootUrl(){
179
  return Mage::helper('connectorhub/connector_config')->getConnectorHubRootUrl();
180
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
  }
25
 
26
  const DEFAULT_CURLOPT_TIMEOUT = 60;
27
 
28
+ const ERROR_LOG_FILE = 'connectorhub_error.log';
29
+
30
  protected $_serviceType = null;
31
 
32
+ // ======================= API Core Functions ======================= //
33
+ protected function _coreMakeRequest($requestUrl, $requestPostData){
34
+ $rawResponse = null;
35
+ try{
36
+ $requestCh = curl_init();
37
+ curl_setopt($requestCh, CURLOPT_URL, $requestUrl);
38
+ curl_setopt($requestCh, CURLOPT_POST, 1);
39
+ curl_setopt($requestCh, CURLOPT_POSTFIELDS, $requestPostData);
40
+ curl_setopt($requestCh, CURLOPT_SSL_VERIFYPEER, $this->_getCurlSslVerifyPeer());
41
+ curl_setopt($requestCh, CURLOPT_RETURNTRANSFER, 1);
42
+ curl_setopt($requestCh, CURLOPT_TIMEOUT, self::DEFAULT_CURLOPT_TIMEOUT);
43
+ $rawResponse = curl_exec($requestCh);
44
+ $curlError = curl_error($requestCh);
45
+ if(!!$curlError){
46
+ Mage::log($curlError, null, self::ERROR_LOG_FILE, true);
47
+ }
48
+ curl_close($requestCh);
49
+ }catch (Exception $ex){
50
+ Mage::log($ex->getMessage(), null, self::ERROR_LOG_FILE, true);
51
+ }
52
+ return $rawResponse;
53
+ }
54
+
55
+ protected function _coreMakeRequestBefore($request){
56
+ return null;
57
+ }
58
+
59
+ protected function _coreMakeRequestAfter($request){
60
+ return null;
61
+ }
62
+
63
  protected function _processRequest($request){
64
  // -------------- Prepare additional request meta -------------- //
65
+ $request['meta'] = $this->_mergeInCreds($request);
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ // -------------- Preparation: log request in debug mode -------------- //
68
+ if($this->getIsDebugMode() && !empty($request['data'])){
69
+ $requestLogData = $request['data'];
70
+ unset($requestLogData['credentials']);
71
+ Mage::log("Request Data:" . serialize($requestLogData), null, "{$this->getServiceType()}_transaction.log", true);
72
  }
73
 
74
+ // -------------- Preparation: Check API user, add usage lock if necessary -------------- //
75
+ $this->_coreMakeRequestBefore($request);
76
+
77
  // -------------- Make request -------------- //
78
+ $dataToken = $this->getToken('data_token', $request); //Data token must pair with 'data_token', provided within $request
79
+ if(!!$dataToken && isset($request['data'])){
80
+ $request['enc_data'] = $this->encryptRequestData($dataToken, $request['data']);
81
+ unset($request['data']);
82
+ }
83
  $requestUrl = $this->_getConnectorHubUrl();
84
+ $requestPostData = array('params' => $this->_compressRequestParams($request));
85
+ $rawResponse = $this->_coreMakeRequest($requestUrl, $requestPostData);
86
+ $response = $this->_uncompressResponseParams($rawResponse);
87
+
88
+ // -------------- Preparation: Check API user, release usage lock if necessary -------------- //
89
+ $this->_coreMakeRequestAfter($request);
 
 
 
 
 
90
 
91
  // -------------- Process response -------------- //
92
  if(!$response){
93
+ if($rawResponse){
94
+ Mage::throwException('Connector Hub: There is an error processing the request.');
95
  }
96
+ Mage::throwException('Connector Hub: Connection failed.');
97
  }
98
  //For now treat reauth the same as fail, the notification will prompt the admin user to update their credentials
99
  switch($response->meta->status){
100
  case self::RESPONSE_STATUS_FAIL:
101
  case self::RESPONSE_STATUS_REAUTH:
102
+ Mage::throwException("Connector Hub ({$this->getServiceType()}): " . $response->meta->message);
103
  break;
104
  case self::RESPONSE_STATUS_SUCCESS:
105
  break;
106
  default:
107
  break;
108
  }
109
+ if(!!$dataToken && !empty($response->enc_data)){
110
+ $response->data = $this->decryptResponseData($dataToken, $response->enc_data);
111
+ unset($response->enc_data);
112
+ }
113
+
114
+ if($this->getIsDebugMode() && !empty($response->data)){
115
+ $responseLogData = json_decode(json_encode($response->data), true);
116
+ unset($responseLogData['credentials']);
117
+ Mage::log("Response Data:" . serialize($responseLogData), null, "{$this->getServiceType()}_transaction.log", true);
118
  }
119
 
120
  return $response;
121
  }
122
 
123
+ protected function _mergeInCreds($request){
124
+ $adminEmail = "";
125
+ if(!!Mage::getSingleton('admin/session')->getUser()){
126
+ $adminEmail = Mage::getSingleton('admin/session')->getUser()->getEmail();
127
+ }
128
+ return array_merge($request['meta'], array(
129
+ 'service_type' => $this->getServiceType(),
130
+ 'service_mode' => $this->getServiceMode($request),
131
+ 'auth_token' => $this->getToken('auth_token', $request),
132
+ 'site_url' => Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB),
133
+ 'account_name' => $adminEmail,
134
+ 'platform' => 'magento',
135
+ 'version' => Mage::getVersion(),
136
+ 'debug_mode' => $this->getIsDebugMode()
137
+ ));
138
+ }
139
+
140
+ // ======================= API Action Functions ======================= //
141
  public function authenticationRequest($credentials){
142
  //For authentication request, directly send the data, rather than encrypted data with token
143
  $request = array(
150
 
151
  //service_mode can be '0'
152
  if(is_null($response->meta->service_mode) || !$response->meta->auth_token || !$response->meta->data_token){
153
+ Mage::throwException("Connector Hub ({$this->getServiceType()}): Authentication failed.");
154
  }
155
 
156
+ $this->saveResponseToken($response);
157
  return $response;
158
  }
159
 
160
 
161
  // ======================= Essential overrides ======================= //
162
+ abstract public function getServiceMode($request = null);
163
+
164
+ public function getIsDebugMode(){
165
+ return false;
166
+ }
167
 
168
  abstract protected function _getConnectorHubUrl();
169
 
177
  return $this->_serviceType;
178
  }
179
 
180
+ /**
181
+ * Get token by name, support mutliple service mode, does NOT support multiple API user accounts
182
+ *
183
+ * @param string $tokenName Typically 'auth_token' or 'data_token'
184
+ * @param unknown_type $serviceMode For multiple service modes, typically: test/beta/sandbox/live
185
+ * @param unknown_type $userId For multiple users on the same API account, can be string value (user email)
186
+ * @return unknown
187
+ */
188
+ public function getToken($tokenName, $request){
189
+ $serviceMode = $this->getServiceMode($request);
190
  //Load from DB, no cache
191
  $coreConfigData = Mage::getModel('core/config_data')->load($this->_getConfigDataBasePath('tokens'), 'path');
192
  $existingToken = json_decode($coreConfigData->getValue(), 1);
196
  return null;
197
  }
198
 
199
+ public function saveResponseToken($response){
200
  //Save to DB, no cache
201
  $coreConfigData = Mage::getModel('core/config_data')->load($this->_getConfigDataBasePath('tokens'), 'path');
202
+ //Global config
203
+ $coreConfigData->setScope('default');
204
+ $coreConfigData->setScopeId(0);
205
+ $coreConfigData->setpath($this->_getConfigDataBasePath('tokens')); //In case the first time save
206
 
207
  $existingToken = json_decode($coreConfigData->getValue(), 1);
208
  $existingToken[$response->meta->service_mode] = array(
214
  return;
215
  }
216
 
217
+ public function encryptRequestData($dataToken, $requestData){
 
 
 
218
  $encData = Mage::helper('connectorhub/mcrypt')->init($dataToken)->encrypt(json_encode($requestData));
219
  return base64_encode($encData);
220
  }
221
+
222
+ public function decryptResponseData($dataToken, $responseData){
223
+ $decData = Mage::helper('connectorhub/mcrypt')->init($dataToken)->decrypt(base64_decode($responseData));
224
+ return json_decode($decData);
225
+ }
226
 
227
  protected function _getCurlSslVerifyPeer(){
228
  $sslVerifyPeer = 0;
240
  protected function _getConnectorHubRootUrl(){
241
  return Mage::helper('connectorhub/connector_config')->getConnectorHubRootUrl();
242
  }
243
+
244
+ protected function _compressRequestParams($request){
245
+ return base64_encode(gzcompress(json_encode($request)));
246
+ }
247
+
248
+ protected function _uncompressResponseParams($rawResponse){
249
+ $response = json_decode(gzuncompress(base64_decode($rawResponse)));
250
+ if(!$response){
251
+ //Fall back to non-compressed logic
252
+ $response = json_decode(base64_decode($rawResponse));
253
+ }
254
+ return $response;
255
+ }
256
 
257
  }
app/code/community/Harapartners/ConnectorHub/Model/Rewrite/Paypal/Config.php CHANGED
@@ -19,20 +19,14 @@ class Harapartners_ConnectorHub_Model_Rewrite_Paypal_Config extends Mage_Paypal_
19
  public function __get($key){
20
  if(strcmp($key, 'verifyPeer') == 0 || strcmp($key, 'verify_peer') == 0){
21
  if($this->_isStagingMode === null){
22
- $this->_isStagingMode = 0;
23
- try{
24
- $curlResource = curl_init("https://www.paypal.com/");
25
- curl_setopt($curlResource, CURLOPT_TIMEOUT, 3);
26
- curl_setopt($curlResource, CURLOPT_RETURNTRANSFER, false);
27
- curl_setopt($curlResource, CURLOPT_SSL_VERIFYPEER, true);
28
- curl_exec($curlResource);
29
- $curlError = curl_error($curlResource);
30
- curl_close($curlResource);
31
- if(!!$curlError){
32
  $this->_isStagingMode = 1;
33
  }
34
- }catch (Exception $ex){
35
- $this->_isStagingMode = 1;
36
  }
37
  }
38
  if($this->_isStagingMode == 1){
@@ -49,6 +43,7 @@ class Harapartners_ConnectorHub_Model_Rewrite_Paypal_Config extends Mage_Paypal_
49
  return 'Hara_SI_MagentoCE_PPA';
50
  }
51
  }
 
52
  private function _isModuleActive($code) {
53
  $module = Mage::getConfig()->getNode("modules/$code");
54
  $model = Mage::getConfig()->getNode("global/models/$code");
19
  public function __get($key){
20
  if(strcmp($key, 'verifyPeer') == 0 || strcmp($key, 'verify_peer') == 0){
21
  if($this->_isStagingMode === null){
22
+ $this->_isStagingMode = 1;
23
+ if(!empty($_SERVER['HTTP_REFERER'])){
24
+ $refererUrlInfo = parse_url($_SERVER['HTTP_REFERER']);
25
+ if(!empty($refererUrlInfo['scheme']) && $refererUrlInfo['scheme'] == 'https'){
26
+ $this->_isStagingMode = 0;
27
+ }else{
 
 
 
 
28
  $this->_isStagingMode = 1;
29
  }
 
 
30
  }
31
  }
32
  if($this->_isStagingMode == 1){
43
  return 'Hara_SI_MagentoCE_PPA';
44
  }
45
  }
46
+
47
  private function _isModuleActive($code) {
48
  $module = Mage::getConfig()->getNode("modules/$code");
49
  $model = Mage::getConfig()->getNode("global/models/$code");
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/All/Index.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Block_Adminhtml_Invoice_All_Index extends Mage_Adminhtml_Block_Widget_Grid_Container {
14
+
15
+ public function __construct() {
16
+ parent::__construct ();
17
+ $this->_blockGroup = 'speedtax';
18
+ $this->_controller = 'adminhtml_invoice_all_index';
19
+ $this->_headerText = Mage::helper ( 'speedtax' )->__ ( 'SalesTax Invoices' );
20
+ $this->_removeButton('add');
21
+ }
22
+
23
+ public function getGridHtml() {
24
+ return $this->getHeaderInfoHtml() . parent::getGridHtml();
25
+ }
26
+
27
+ public function getHeaderInfoHtml(){
28
+ $headerInfoHtml = <<< INFO_HTML
29
+ <div class="grid-top-info" style="background: none repeat scroll 0 0 #E7EFEF; border: 1px solid #CDDDDD; padding: 10px 20px 10px 20px; margin-bottom: 20px;">
30
+ <p>By default Magento invoices will be posted to SalesTax when paid; and most orders should be in the <b>Posted</b> status.</p>
31
+ <p>The <b>Failsafe</b> status is for invoices that are paid but cannot be posted to SalesTax. These invoices can be processed in batch by either 1) system cronjobs or 2) the <b><i>Post To SalesTax</i></b> action.</p>
32
+ <p>The <b>Pending</b> status is for invoices that are paid, and by default not to be posted to SalesTax. These invoices are probably from historical orders before the SalesTax integration.</p>
33
+ </div>
34
+ INFO_HTML;
35
+ return $headerInfoHtml;
36
+ }
37
+
38
+ }
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/All/Index/Grid.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Block_Adminhtml_Invoice_All_Index_Grid extends Mage_Adminhtml_Block_Widget_Grid {
14
+
15
+ public function __construct(){
16
+ parent::__construct();
17
+ $this->setId('speedtaxInvoiceAllGrid');
18
+ }
19
+
20
+ protected function _prepareCollection(){
21
+ $collection = Mage::getModel('sales/order_invoice')->getCollection();
22
+ $this->setCollection($collection);
23
+ $this->setDefaultSort('created_at');
24
+ $this->setDefaultDir('desc');
25
+ return parent::_prepareCollection();
26
+ }
27
+
28
+ protected function _prepareColumns()
29
+ {
30
+ $this->addColumn('increment_id', array(
31
+ 'header' => Mage::helper('speedtax')->__('Magento Invoice #'),
32
+ 'index' => 'increment_id',
33
+ 'type' => 'text',
34
+ 'align' => 'right',
35
+ ));
36
+
37
+ $this->addColumn('action',
38
+ array(
39
+ 'header' => Mage::helper('sales')->__('Invoice Details'),
40
+ 'width' => '100px',
41
+ 'type' => 'action',
42
+ 'align' => 'right',
43
+ 'getter' => 'getId',
44
+ 'actions' => array(
45
+ array(
46
+ 'caption' => Mage::helper('sales')->__('View'),
47
+ 'url' => array('base'=>'adminhtml/sales_invoice/view'),
48
+ 'field' => 'invoice_id'
49
+ )
50
+ ),
51
+ 'filter' => false,
52
+ 'sortable' => false,
53
+ 'is_system' => true
54
+ ));
55
+
56
+ $this->addColumn('created_at', array(
57
+ 'header' => Mage::helper('speedtax')->__('Magento Invoice Date'),
58
+ 'index' => 'created_at',
59
+ 'type' => 'datetime',
60
+ 'align' => 'right',
61
+ ));
62
+
63
+ $this->addColumn('speedtax_invoice_number', array(
64
+ 'header' => Mage::helper('speedtax')->__('SalesTax Invoice #'),
65
+ 'index' => 'speedtax_invoice_number',
66
+ 'type' => 'text',
67
+ 'align' => 'right',
68
+ ));
69
+
70
+ $this->addColumn('speedtax_transaction_id', array(
71
+ 'header' => Mage::helper('speedtax')->__('SalesTax Transaction ID'),
72
+ 'index' => 'speedtax_transaction_id',
73
+ 'type' => 'text',
74
+ 'align' => 'right',
75
+ ));
76
+
77
+ $this->addColumn('tax_amount', array(
78
+ 'header' => Mage::helper('speedtax')->__('Magento Tax Amount'),
79
+ 'index' => 'tax_amount',
80
+ 'type' => 'currency',
81
+ 'align' => 'right',
82
+ 'currency' => 'order_currency_code',
83
+ ));
84
+
85
+ $this->addColumn('speedtax_tax_amount', array(
86
+ 'header' => Mage::helper('speedtax')->__('SalesTax Tax Amount'),
87
+ 'index' => 'speedtax_tax_amount',
88
+ 'type' => 'currency',
89
+ 'align' => 'right',
90
+ 'currency' => 'order_currency_code',
91
+ ));
92
+
93
+ $this->addColumn('speedtax_invoice_status', array(
94
+ 'header' => Mage::helper('speedtax')->__('SalesTax Invoice Status'),
95
+ 'width' => '100px',
96
+ 'index' => 'speedtax_invoice_status',
97
+ 'type' => 'options',
98
+ 'align' => 'right',
99
+ 'options' => Mage::helper('speedtax')->getSpeedtaxInvoiceStatusValues(),
100
+ ));
101
+
102
+ return parent::_prepareColumns();
103
+ }
104
+
105
+ protected function _prepareMassaction()
106
+ {
107
+ $this->setMassactionIdField('entity_id');
108
+ $this->getMassactionBlock()->setFormFieldName('invoice_ids');
109
+ $this->getMassactionBlock()->setUseSelectAll(false);
110
+
111
+ $this->getMassactionBlock()->addItem('post_selected', array(
112
+ 'label' => Mage::helper('sales')->__('Post To SalesTax'),
113
+ 'url' => $this->getUrl('*/*/massPostToSpeedtax'),
114
+ ));
115
+
116
+ return $this;
117
+ }
118
+
119
+ //No row editing
120
+ public function getRowUrl($row){
121
+ return false;
122
+ }
123
+
124
+ }
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Failsafe/Index.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Block_Adminhtml_Invoice_Failsafe_Index extends Harapartners_SpeedTax_Block_Adminhtml_Invoice_All_Index {
14
+
15
+ public function __construct() {
16
+ parent::__construct ();
17
+ $this->_blockGroup = 'speedtax';
18
+ $this->_controller = 'adminhtml_invoice_failsafe_index';
19
+ $this->_headerText = Mage::helper ( 'speedtax' )->__ ( 'Failsafe Invoices' );
20
+ $this->_removeButton('add');
21
+ }
22
+
23
+ public function getHeaderInfoHtml(){
24
+ $headerInfoHtml = <<< INFO_HTML
25
+ <div class="grid-top-info" style="background: none repeat scroll 0 0 #E7EFEF; border: 1px solid #CDDDDD; padding: 10px 20px 10px 20px; margin-bottom: 20px;">
26
+ <p>Failsafe invoices are paid Magento invoices that are not yet posted to SalesTax. These invoices can be processed in batch either 1) by system cronjobs automatically or 2) by running <b><i>Post To SalesTax</i></b> via the "Actions" dropdown menu next to the "Submit" button.</p>
27
+ </div>
28
+ INFO_HTML;
29
+ return $headerInfoHtml;
30
+ }
31
+
32
+ }
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Failsafe/Index/Grid.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Block_Adminhtml_Invoice_Failsafe_Index_Grid extends Harapartners_SpeedTax_Block_Adminhtml_Invoice_All_Index_Grid {
14
+
15
+ public function __construct(){
16
+ parent::__construct();
17
+ $this->setId('speedtaxInvoiceFailsafeGrid');
18
+ }
19
+
20
+ public function setCollection($collection){
21
+ $collection->addAttributeToFilter('speedtax_invoice_status', Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_FAILSAFE);
22
+ return parent::setCollection($collection);
23
+ }
24
+
25
+ protected function _prepareColumns(){
26
+ parent::_prepareColumns();
27
+ $this->removeColumn('speedtax_invoice_status');
28
+ return $this;
29
+ }
30
+
31
+ protected function _prepareMassaction()
32
+ {
33
+ $this->setMassactionIdField('entity_id');
34
+ $this->getMassactionBlock()->setFormFieldName('invoice_ids');
35
+ $this->getMassactionBlock()->setUseSelectAll(false);
36
+
37
+ $this->getMassactionBlock()->addItem('post_selected', array(
38
+ 'label' => Mage::helper('sales')->__('Post To SalesTax'),
39
+ 'url' => $this->getUrl('*/*/massPostToSpeedtax'),
40
+ ));
41
+
42
+ return $this;
43
+ }
44
+
45
+ //No row editing
46
+ public function getRowUrl($row){
47
+ return false;
48
+ }
49
+
50
+ }
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Rateverification/Index.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Block_Adminhtml_Invoice_Rateverification_Index extends Harapartners_SpeedTax_Block_Adminhtml_Invoice_All_Index {
14
+
15
+ public function __construct() {
16
+ parent::__construct ();
17
+ $this->_blockGroup = 'speedtax';
18
+ $this->_controller = 'adminhtml_invoice_rateverification_index';
19
+ $this->_headerText = Mage::helper ( 'speedtax' )->__ ( 'Verify Invoices with Failsafe Tax Rates' );
20
+ $this->_removeButton('add');
21
+ }
22
+
23
+ public function getHeaderInfoHtml(){
24
+ $headerInfoHtml = <<< INFO_HTML
25
+ <div class="grid-top-info" style="background: none repeat scroll 0 0 #E7EFEF; border: 1px solid #CDDDDD; padding: 10px 20px 10px 20px; margin-bottom: 20px;">
26
+ <p>Invoices in this panel are paid using failsafe rate. For some invoices failsafe rate may be different from the SalesTax rate. In such cases, please reconciliate the difference in SalesTax management panel if necessary.</p>
27
+ </div>
28
+ INFO_HTML;
29
+ return $headerInfoHtml;
30
+ }
31
+
32
+ }
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Invoice/Rateverification/Index/Grid.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Block_Adminhtml_Invoice_Rateverification_Index_Grid extends Harapartners_SpeedTax_Block_Adminhtml_Invoice_All_Index_Grid {
14
+
15
+ public function __construct(){
16
+ parent::__construct();
17
+ $this->setId('speedtaxInvoiceRateVerificationGrid');
18
+ }
19
+
20
+ public function setCollection($collection){
21
+ $collection->addAttributeToFilter('is_speedtax_failsafe_calculation', 1);
22
+ $collection->getSelect()->columns(array(
23
+ 'tax_amount_difference' => new Zend_Db_Expr("IFNULL(`main_table`.`speedtax_tax_amount`, 0) - IFNULL(`main_table`.`tax_amount`, 0)"),
24
+ 'has_tax_amount_difference' => new Zend_Db_Expr("IF(IFNULL(`main_table`.`speedtax_tax_amount`, 0) - IFNULL(`main_table`.`tax_amount`, 0) = 0, 0, 1)"),
25
+ ));
26
+
27
+ //Re-wrap the collection to support generic form sort and filter
28
+ $outerCollection = Mage::getModel('sales/order_invoice')->getCollection();
29
+ $outerCollection->getSelect()->reset();
30
+ $outerCollection->getSelect()->from(array('main_table' => $collection->getSelect()));
31
+ return parent::setCollection($outerCollection);
32
+ }
33
+
34
+ protected function _prepareColumns(){
35
+ parent::_prepareColumns();
36
+ $this->addColumn('tax_amount_difference', array(
37
+ 'header' => Mage::helper('speedtax')->__('Tax Difference (SalesTax - Magento)'),
38
+ 'index' => 'tax_amount_difference',
39
+ 'type' => 'currency',
40
+ 'align' => 'right',
41
+ 'currency' => 'order_currency_code',
42
+ ));
43
+ $this->addColumn('has_tax_amount_difference', array(
44
+ 'header' => Mage::helper('speedtax')->__('Has Tax Difference'),
45
+ 'index' => 'has_tax_amount_difference',
46
+ 'type' => 'options',
47
+ 'align' => 'right',
48
+ 'options' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toArray(),
49
+ ));
50
+ return $this;
51
+ }
52
+
53
+ protected function _prepareMassaction(){
54
+ return $this;
55
+ }
56
+
57
+ //No row editing
58
+ public function getRowUrl($row){
59
+ return false;
60
+ }
61
+
62
+ }
app/code/community/Harapartners/SpeedTax/Block/Adminhtml/Notification.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license [^]
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+
14
+ class Harapartners_SpeedTax_Block_Adminhtml_Notification extends Mage_Adminhtml_Block_Template {
15
+
16
+ protected function _toHtml() {
17
+ $htmlContent = "";
18
+ $notificationDisabled = json_decode(Mage::getStoreConfig(Harapartners_SpeedTax_Helper_Data::XML_PATH_NOTIFICATION_DISABLED_COMPRESS), 1);
19
+
20
+ //TODO: add ACL restriction to screen some messages
21
+ $speedtaxMessages = array();
22
+
23
+ // ---------------- Tax on Discount ---------------- //
24
+ if(!Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT)
25
+ && empty($notificationDisabled[Harapartners_SpeedTax_Helper_Data::NOTIFICATION_KEY_TAX_ON_DISCOUNT])
26
+ ){
27
+ $speedtaxMessages[Harapartners_SpeedTax_Helper_Data::NOTIFICATION_KEY_TAX_ON_DISCOUNT] = '
28
+ Your tax configuration "Calculation Setting >> Apply Customer Tax" is set to <strong class="label">Before Discount</strong>, which is the default value.
29
+ If your business logic requires tax <strong class="label">After Discount</strong>, please click <a href="' . Mage::helper("adminhtml")->getUrl("adminhtml/system_config/edit", array("section" => "tax")). '">HERE</a> to update the setting.
30
+ <i><a href="' . Mage::helper("adminhtml")->getUrl("speedtax_adminhtml/notification/disable", array("notification_key" => Harapartners_SpeedTax_Helper_Data::NOTIFICATION_KEY_TAX_ON_DISCOUNT)) . '">Dismiss this message</a></i>';
31
+ }
32
+
33
+ // ---------------- Output ---------------- //
34
+ foreach($speedtaxMessages as $messageKey => $messageContent){
35
+ $htmlContent .= <<< HTML_CONTENT
36
+ <div class="notification-global">
37
+ <strong class="label">SalesTax notification:</strong> $messageContent
38
+ </div>
39
+ HTML_CONTENT;
40
+ }
41
+ return $htmlContent;
42
+ }
43
+
44
+ }
app/code/community/Harapartners/SpeedTax/Helper/Connector/Data.php CHANGED
@@ -12,10 +12,10 @@
12
  */
13
  class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstract {
14
 
15
- const TAX_SHIPPING_LINEITEM_TAX_CLASS = 'TAX_SHIPPING';
16
- const TAX_SHIPPING_LINEITEM_REFERNCE_NAME = 'TAX_SHIPPING';
17
 
18
- protected $_productTaxClassNoneTaxableId = 0; //Magento default
19
  // protected $_allowedCountryIds = array('US', 'CA');
20
 
21
  protected $_shipFromAddress = null;
@@ -36,7 +36,13 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
36
  if($mageQuoteItem->getProduct()->getTaxClassId() == $this->_productTaxClassNoneTaxableId){
37
  continue;
38
  }
39
- if($mageQuoteItem->getRowTotal() - $mageQuoteItem->getDiscountAmount() <= 0){
 
 
 
 
 
 
40
  continue;
41
  }
42
 
@@ -49,7 +55,7 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
49
 
50
  //Price of row total, not unit price
51
  $lineItemPrice = new stdClass();
52
- $lineItemPrice->decimalValue = $mageQuoteItem->getRowTotal() - $mageQuoteItem->getDiscountAmount();
53
  $lineItem->salesAmount = $lineItemPrice;
54
 
55
  $lineItem->lineItemNumber = count( $sptxInvoice->lineItems );
@@ -73,7 +79,7 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
73
  //Clear the invoice number so that the request is just a query
74
  $mageOrderAddress = $mageOrderInvoice->getShippingAddress();
75
  $sptxInvoice = new stdClass();
76
-
77
  //Important to keep unique, invoice should already be attached to the order, count starts from 1
78
  $sptxInvoice->invoiceNumber =
79
  $mageOrderInvoice->getOrder()->getIncrementId()
@@ -84,6 +90,13 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
84
  if(!$mageItem->getTaxAmount() || $mageItem->getTaxAmount() <= 0.0){
85
  continue;
86
  }
 
 
 
 
 
 
 
87
  $lineItem = new stdClass();
88
  $lineItem->productCode = $this->_getProductCode($mageItem);
89
  $lineItem->customReference = $mageItem->getOrderItemId(); //This is during invoice creation, no ID available
@@ -93,7 +106,7 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
93
 
94
  //Price of row total, not unit price
95
  $lineItemPrice = new stdClass();
96
- $lineItemPrice->decimalValue = $mageItem->getRowTotal() - $mageItem->getDiscountAmount();
97
  $lineItem->salesAmount = $lineItemPrice;
98
 
99
  $lineItem->lineItemNumber = count( $sptxInvoice->lineItems );
@@ -120,6 +133,8 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
120
  //Clear the invoice number so that the request is just a query
121
  $mageOrderAddress = $mageOrderCreditmemo->getShippingAddress();
122
  $sptxInvoice = new stdClass();
 
 
123
  //Important to keep unique, credit memo not yet attached to the order, count ++ so that it starts from 1
124
  $sptxInvoice->invoiceNumber =
125
  $mageOrderCreditmemo->getOrder()->getIncrementId()
@@ -130,6 +145,13 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
130
  if(!$mageItem->getTaxAmount() || $mageItem->getTaxAmount() <= 0.0){
131
  continue;
132
  }
 
 
 
 
 
 
 
133
  $lineItem = new stdClass();
134
  $lineItem->productCode = $this->_getProductCode($mageItem);
135
  $lineItem->customReference = $mageItem->getOrderItemId(); //This is during credit memo creation, no ID available
@@ -139,7 +161,7 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
139
 
140
  //Price of row total, not unit price
141
  $lineItemPrice = new stdClass();
142
- $lineItemPrice->decimalValue = $mageItem->getRowTotal() - $mageItem->getDiscountAmount();
143
  $lineItem->salesAmount = $lineItemPrice;
144
 
145
  $lineItem->lineItemNumber = count( $sptxInvoice->lineItems );
@@ -206,7 +228,7 @@ class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstr
206
  $street = implode(' ', $address->getStreet()); //In case of multiple line address
207
 
208
  $this->_shipToAddress->address1 = $street;
209
- $this->_shipToAddress->address2 = $city . ", " . $state . " " . $zip; //. ", " . $country;
210
  }
211
  return $this->_shipToAddress;
212
  }
12
  */
13
  class Harapartners_SpeedTax_Helper_Connector_Data extends Mage_Core_Helper_Abstract {
14
 
15
+ const TAX_SHIPPING_LINEITEM_TAX_CLASS = 'TAX_SHIPPING';
16
+ const TAX_SHIPPING_LINEITEM_REFERNCE_NAME = 'TAX_SHIPPING';
17
 
18
+ protected $_productTaxClassNoneTaxableId = 0; //Magento default
19
  // protected $_allowedCountryIds = array('US', 'CA');
20
 
21
  protected $_shipFromAddress = null;
36
  if($mageQuoteItem->getProduct()->getTaxClassId() == $this->_productTaxClassNoneTaxableId){
37
  continue;
38
  }
39
+
40
+ //Respect Magento tax/discount config
41
+ $taxableAmount = $mageQuoteItem->getRowTotal();
42
+ if(!!Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, $mageQuoteItem->getStoreId())){
43
+ $taxableAmount = $taxableAmount - $mageQuoteItem->getDiscountAmount() + $mageQuoteItem->getHiddenTaxAmount();
44
+ }
45
+ if($taxableAmount <= 0){
46
  continue;
47
  }
48
 
55
 
56
  //Price of row total, not unit price
57
  $lineItemPrice = new stdClass();
58
+ $lineItemPrice->decimalValue = $taxableAmount;
59
  $lineItem->salesAmount = $lineItemPrice;
60
 
61
  $lineItem->lineItemNumber = count( $sptxInvoice->lineItems );
79
  //Clear the invoice number so that the request is just a query
80
  $mageOrderAddress = $mageOrderInvoice->getShippingAddress();
81
  $sptxInvoice = new stdClass();
82
+ $sptxInvoice->lineItems = array();
83
  //Important to keep unique, invoice should already be attached to the order, count starts from 1
84
  $sptxInvoice->invoiceNumber =
85
  $mageOrderInvoice->getOrder()->getIncrementId()
90
  if(!$mageItem->getTaxAmount() || $mageItem->getTaxAmount() <= 0.0){
91
  continue;
92
  }
93
+
94
+ //Respect Magento tax/discount config
95
+ $taxableAmount = $mageItem->getRowTotal();
96
+ if(!!Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, $mageItem->getStoreId())){
97
+ $taxableAmount = $taxableAmount - $mageItem->getDiscountAmount() + $mageItem->getHiddenTaxAmount();
98
+ }
99
+
100
  $lineItem = new stdClass();
101
  $lineItem->productCode = $this->_getProductCode($mageItem);
102
  $lineItem->customReference = $mageItem->getOrderItemId(); //This is during invoice creation, no ID available
106
 
107
  //Price of row total, not unit price
108
  $lineItemPrice = new stdClass();
109
+ $lineItemPrice->decimalValue = $taxableAmount;
110
  $lineItem->salesAmount = $lineItemPrice;
111
 
112
  $lineItem->lineItemNumber = count( $sptxInvoice->lineItems );
133
  //Clear the invoice number so that the request is just a query
134
  $mageOrderAddress = $mageOrderCreditmemo->getShippingAddress();
135
  $sptxInvoice = new stdClass();
136
+ $sptxInvoice->lineItems = array();
137
+
138
  //Important to keep unique, credit memo not yet attached to the order, count ++ so that it starts from 1
139
  $sptxInvoice->invoiceNumber =
140
  $mageOrderCreditmemo->getOrder()->getIncrementId()
145
  if(!$mageItem->getTaxAmount() || $mageItem->getTaxAmount() <= 0.0){
146
  continue;
147
  }
148
+
149
+ //Respect Magento tax/discount config
150
+ $taxableAmount = $mageItem->getRowTotal();
151
+ if(!!Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT, $mageItem->getStoreId())){
152
+ $taxableAmount = $taxableAmount - $mageItem->getDiscountAmount() + $mageItem->getHiddenTaxAmount();
153
+ }
154
+
155
  $lineItem = new stdClass();
156
  $lineItem->productCode = $this->_getProductCode($mageItem);
157
  $lineItem->customReference = $mageItem->getOrderItemId(); //This is during credit memo creation, no ID available
161
 
162
  //Price of row total, not unit price
163
  $lineItemPrice = new stdClass();
164
+ $lineItemPrice->decimalValue = $taxableAmount;
165
  $lineItem->salesAmount = $lineItemPrice;
166
 
167
  $lineItem->lineItemNumber = count( $sptxInvoice->lineItems );
228
  $street = implode(' ', $address->getStreet()); //In case of multiple line address
229
 
230
  $this->_shipToAddress->address1 = $street;
231
+ $this->_shipToAddress->address2 = $city . ", " . $state . " " . $zip; //. ", " . $county;
232
  }
233
  return $this->_shipToAddress;
234
  }
app/code/community/Harapartners/SpeedTax/Helper/Connector/Speedtax.php CHANGED
@@ -25,14 +25,25 @@ class Harapartners_SpeedTax_Helper_Connector_Speedtax extends Harapartners_Conne
25
  protected $_serviceType = 'speedtax';
26
 
27
  // ======================= Essential overrides ======================= //
28
- public function getServiceMode(){
 
29
  $serviceMode = Harapartners_ConnectorHub_Helper_Connector_Core::REQUEST_SERVICE_MODE_PRODUCTION;
 
 
30
  if(!!Mage::getStoreConfig($this->_getConfigDataBasePath('is_test_mode'))){
31
  $serviceMode = Harapartners_ConnectorHub_Helper_Connector_Core::REQUEST_SERVICE_MODE_TEST;
32
  }
 
 
 
 
33
  return $serviceMode;
34
  }
35
 
 
 
 
 
36
  protected function _getConnectorHubUrl(){
37
  return $this->_getConnectorHubRootUrl() . 'SpeedTax.php';
38
  }
@@ -77,35 +88,19 @@ class Harapartners_SpeedTax_Helper_Connector_Speedtax extends Harapartners_Conne
77
  return $response->data->result;
78
  }
79
 
80
- public function cancelAllOrderTransactions($invoiceNumbers){
81
  $credentials = $this->_prepareCredentials();
82
  $request = array(
83
  'meta' => array(
84
- 'action' => $actionType
85
  ),
86
  'data' => array(
87
  'credentials' => $credentials,
88
- 'invoice' => $sptxInvoice
89
  )
90
  );
91
-
92
  $response = $this->_processRequest($request);
93
-
94
- //Essential validation!
95
- if(!$response->data || !$response->data->result){
96
- Mage::throwException('Invalid tax response');
97
- }
98
- $responseResult = $response->data->result;
99
- switch ($responseResult->resultType) {
100
- case self::RESPONSE_TYPE_SUCCESS:
101
- break;
102
- case self::RESPONSE_TYPE_FAILED_WITH_ERRORS:
103
- case self::RESPONSE_TYPE_FAILED_INVOICE_NUMBER:
104
- default :
105
- Mage::throwException('Tax request failed');
106
- break;
107
- }
108
-
109
  return $response;
110
  }
111
 
@@ -124,24 +119,12 @@ class Harapartners_SpeedTax_Helper_Connector_Speedtax extends Harapartners_Conne
124
  $response = $this->_loadCachedInvoiceResponse($sptxInvoice, $actionType);
125
  if(!$response){
126
  $response = $this->_processRequest($request);
127
- $this->_saveCachedInvoiceResponse($response, $sptxInvoice, $actionType);
128
- }
129
-
130
- //Essential validation!
131
- if(!$response->data || !$response->data->result){
132
- Mage::throwException('Invalid tax response');
133
  }
134
- $responseResult = $response->data->result;
135
- switch ($responseResult->resultType) {
136
- case self::RESPONSE_TYPE_SUCCESS:
137
- break;
138
- case self::RESPONSE_TYPE_FAILED_WITH_ERRORS:
139
- case self::RESPONSE_TYPE_FAILED_INVOICE_NUMBER:
140
- default :
141
- Mage::throwException('Tax request failed');
142
- break;
143
- }
144
-
145
  return $response;
146
  }
147
 
@@ -163,6 +146,23 @@ class Harapartners_SpeedTax_Helper_Connector_Speedtax extends Harapartners_Conne
163
  return true;
164
  }
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  protected function _isCacheRequestAllowed($actionType){
167
  $allRequestCache = false;
168
  switch($actionType){
25
  protected $_serviceType = 'speedtax';
26
 
27
  // ======================= Essential overrides ======================= //
28
+ public function getServiceMode($request = null){
29
+ //Always default to production for safety
30
  $serviceMode = Harapartners_ConnectorHub_Helper_Connector_Core::REQUEST_SERVICE_MODE_PRODUCTION;
31
+
32
+ //Check from request first (in case it's a new authorization), default to last saved config value
33
  if(!!Mage::getStoreConfig($this->_getConfigDataBasePath('is_test_mode'))){
34
  $serviceMode = Harapartners_ConnectorHub_Helper_Connector_Core::REQUEST_SERVICE_MODE_TEST;
35
  }
36
+ if(isset($request['meta']['credentials']['service_mode'])){
37
+ $serviceMode = $request['meta']['credentials']['service_mode']; //Allow 0 and other empty values
38
+ }
39
+
40
  return $serviceMode;
41
  }
42
 
43
+ public function getIsDebugMode(){
44
+ return Mage::getStoreConfig($this->_getConfigDataBasePath('is_debug_transaction'));
45
+ }
46
+
47
  protected function _getConnectorHubUrl(){
48
  return $this->_getConnectorHubRootUrl() . 'SpeedTax.php';
49
  }
88
  return $response->data->result;
89
  }
90
 
91
+ public function batchVoidInvoices($invoiceNumbers){
92
  $credentials = $this->_prepareCredentials();
93
  $request = array(
94
  'meta' => array(
95
+ 'action' => self::REQUEST_ACTION_BATCH_VOID_INVOICES
96
  ),
97
  'data' => array(
98
  'credentials' => $credentials,
99
+ 'invoice_numbers' => $invoiceNumbers
100
  )
101
  );
 
102
  $response = $this->_processRequest($request);
103
+ $this->_validateResponse($response);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  return $response;
105
  }
106
 
119
  $response = $this->_loadCachedInvoiceResponse($sptxInvoice, $actionType);
120
  if(!$response){
121
  $response = $this->_processRequest($request);
122
+ //Save cache upon successful transactions only
123
+ if(isset($response->meta->status) && $response->meta->status == Harapartners_ConnectorHub_Helper_Connector_Core::RESPONSE_STATUS_SUCCESS){
124
+ $this->_saveCachedInvoiceResponse($response, $sptxInvoice, $actionType);
125
+ }
 
 
126
  }
127
+ $this->_validateResponse($response);
 
 
 
 
 
 
 
 
 
 
128
  return $response;
129
  }
130
 
146
  return true;
147
  }
148
 
149
+ protected function _validateResponse($response){
150
+ //Essential validation for SpeedTax response data structure
151
+ if(empty($response->data->result->resultType)){
152
+ Mage::throwException('Invalid tax response');
153
+ }
154
+ switch ($response->data->result->resultType) {
155
+ case self::RESPONSE_TYPE_SUCCESS:
156
+ break;
157
+ case self::RESPONSE_TYPE_FAILED_WITH_ERRORS:
158
+ case self::RESPONSE_TYPE_FAILED_INVOICE_NUMBER:
159
+ default :
160
+ Mage::throwException('Tax request failed');
161
+ break;
162
+ }
163
+ return $this;
164
+ }
165
+
166
  protected function _isCacheRequestAllowed($actionType){
167
  $allRequestCache = false;
168
  switch($actionType){
app/code/community/Harapartners/SpeedTax/Helper/Data.php CHANGED
@@ -12,6 +12,12 @@
12
  */
13
  class Harapartners_SpeedTax_Helper_Data extends Mage_Core_Helper_Abstract {
14
 
 
 
 
 
 
 
15
  protected $_xmlPathPrefix = 'speedtax/speedtax/';
16
 
17
  // =========================== config and essential flags =========================== //
@@ -26,5 +32,19 @@ class Harapartners_SpeedTax_Helper_Data extends Mage_Core_Helper_Abstract {
26
  public function isAddressValidationOn($address, $storeId) {
27
  return Mage::getStoreConfig( $this->_xmlPathPrefix . 'validate_address', $storeId);
28
  }
 
 
 
 
29
 
 
 
 
 
 
 
 
 
 
 
30
  }
12
  */
13
  class Harapartners_SpeedTax_Helper_Data extends Mage_Core_Helper_Abstract {
14
 
15
+ // Notification settings
16
+ const XML_PATH_NOTIFICATION_DISABLED_COMPRESS = 'speedtax/notification/disabled_compress';
17
+ const NOTIFICATION_KEY_TAX_ON_DISCOUNT = 'tax_on_discount';
18
+ const ERROR_LOG_FILE = 'speedtax_error.log';
19
+ const DEFAULT_MAGENTO_COLLECTION_PAGE_SIZE = 50;
20
+
21
  protected $_xmlPathPrefix = 'speedtax/speedtax/';
22
 
23
  // =========================== config and essential flags =========================== //
32
  public function isAddressValidationOn($address, $storeId) {
33
  return Mage::getStoreConfig( $this->_xmlPathPrefix . 'validate_address', $storeId);
34
  }
35
+
36
+ public function isFailsafeEnabled(){
37
+ return Mage::getStoreConfig ( 'speedtax/failsafe/is_enabled' );
38
+ }
39
 
40
+ public function getSpeedtaxInvoiceStatusValues() {
41
+ return array(
42
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_PENDING => Mage::helper('speedtax')->__('Pending'),
43
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_POSTED => Mage::helper('speedtax')->__('Posted'),
44
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_VOID => Mage::helper('speedtax')->__('Void'),
45
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_ERROR => Mage::helper('speedtax')->__('Error'),
46
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_FAILSAFE => Mage::helper('speedtax')->__('Failsafe'),
47
+ );
48
+ }
49
+
50
  }
app/code/community/Harapartners/SpeedTax/Helper/Failsafe.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license [^]
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+ class Harapartners_SpeedTax_Helper_Failsafe extends Mage_Core_Helper_Abstract {
14
+
15
+ const FALLBACK_CALCULATION_PRECISION = 4;
16
+
17
+ public function updateFailsafeRate(Mage_Sales_Model_Quote_Address $mageQuoteAddress, $responseResult){
18
+ if(!$mageQuoteAddress || !$responseResult){
19
+ return;
20
+ }
21
+
22
+ $decPrecision = pow(0.1, Harapartners_SpeedTax_Helper_Failsafe::FALLBACK_CALCULATION_PRECISION);
23
+ $requestData = array();
24
+ $sptxInvoice = Mage::helper('speedtax/connector_data')->prepareSpeedTaxInvoiceByMageQuoteAddress($mageQuoteAddress);
25
+ if(!empty($sptxInvoice->lineItems)){
26
+ foreach($sptxInvoice->lineItems as $lineItem){
27
+ if(!empty($lineItem->customReference) && !empty($lineItem->salesAmount->decimalValue)){
28
+ $requestData[$lineItem->customReference] = $lineItem->salesAmount->decimalValue;
29
+ }
30
+ }
31
+ }
32
+ $responseData = array();
33
+ if(!empty($responseResult->lineItemBundles->lineItems)){
34
+ foreach($responseResult->lineItemBundles->lineItems as $lineItem){
35
+ if(!empty($lineItem->customReference) && !empty($lineItem->taxAmount->decimalValue)){
36
+ $responseData[$lineItem->customReference] = $lineItem->taxAmount->decimalValue;
37
+ }
38
+ }
39
+ }
40
+
41
+ $taxRate = 0.0; //This is a percentage
42
+ foreach($requestData as $customReference => $salesAmount){
43
+ if($salesAmount > $decPrecision && isset($responseData[$customReference])) {
44
+ $taxRate = round($responseData[$customReference] / $salesAmount * 100.0, Harapartners_SpeedTax_Helper_Failsafe::FALLBACK_CALCULATION_PRECISION);
45
+ break;
46
+ }
47
+ }
48
+
49
+ //Do not update zero tax rates
50
+ if($taxRate <= $decPrecision){
51
+ return;
52
+ }
53
+
54
+ $countryId = $mageQuoteAddress->getCountryId();
55
+ $regionId = $mageQuoteAddress->getRegionId();
56
+ $postcode = $mageQuoteAddress->getPostcode(); //$postcode = preg_replace('/[^0-9\-]*/', '', $address->getPostcode()); //US zip code clean up
57
+ $failsafeCalRate = Mage::getModel('speedtax/failsafe_calculation_rate');
58
+ $failsafeCalRate->loadByCountryIdRegionIdPostcode($countryId, $regionId, $postcode);
59
+
60
+ if($failsafeCalRate->getTaxRate() != $taxRate){
61
+ $failsafeCalRate->setData(array(
62
+ 'country_id' => $countryId,
63
+ 'region_id' => $regionId,
64
+ 'postcode' => $postcode,
65
+ 'tax_rate' => $taxRate
66
+ ));
67
+ $failsafeCalRate->save();
68
+ }
69
+
70
+ return null;
71
+ }
72
+
73
+ }
app/code/community/Harapartners/SpeedTax/Helper/Processor.php CHANGED
@@ -18,6 +18,7 @@ class Harapartners_SpeedTax_Helper_Processor extends Mage_Core_Helper_Abstract {
18
  const SPEEDTAX_INVOICE_STATUS_POSTED = 100;
19
  const SPEEDTAX_INVOICE_STATUS_VOID = 200;
20
  const SPEEDTAX_INVOICE_STATUS_ERROR = 300;
 
21
 
22
  // ========================== Actions ========================== //
23
  public function queryQuoteAddress(Mage_Sales_Model_Quote_Address $mageQuoteAddress){
@@ -87,7 +88,7 @@ class Harapartners_SpeedTax_Helper_Processor extends Mage_Core_Helper_Abstract {
87
  return false;
88
  }
89
  //No caching allowed for order invoice
90
- $responseResult = Mage::helper('speedtax/connector_speedtax')->cancelAllOrderTransactions($invoiceNumbers);
91
 
92
  //Update status
93
  $batchVoidResults = json_decode($responseResult->data->result->batchVoidResults, 1);
@@ -129,8 +130,8 @@ class Harapartners_SpeedTax_Helper_Processor extends Mage_Core_Helper_Abstract {
129
  $mageQuoteItem->setTaxPercent (sprintf("%.4f", 100*$taxAmount/($mageQuoteItem->getRowTotal() - $mageQuoteItem->getDiscountAmount())));
130
  }
131
  }
132
- if(!!$this->_getTaxShippingAmount($responseResult)){
133
- $taxShippingAmount = $this->_getTaxShippingAmount($responseResult);
134
  $mageQuoteAddress->setShippingTaxAmount($taxShippingAmount);
135
  $mageQuoteAddress->setBaseShippingTaxAmount($taxShippingAmount);
136
  }
@@ -166,12 +167,14 @@ class Harapartners_SpeedTax_Helper_Processor extends Mage_Core_Helper_Abstract {
166
  return 0.0;
167
  }
168
 
169
- protected function _getTaxShippingAmount() {
170
- foreach($responseResult->lineItemBundles->lineItems as $responseLineItem){
171
- if($responseLineItem->productCode == self::TAX_SHIPPING_LINEITEM_TAX_CLASS){
172
- return $responseLineItem->taxAmount->decimalValue;
173
- }
174
- }
 
 
175
  return 0.0;
176
  }
177
 
18
  const SPEEDTAX_INVOICE_STATUS_POSTED = 100;
19
  const SPEEDTAX_INVOICE_STATUS_VOID = 200;
20
  const SPEEDTAX_INVOICE_STATUS_ERROR = 300;
21
+ const SPEEDTAX_INVOICE_STATUS_FAILSAFE = 900;
22
 
23
  // ========================== Actions ========================== //
24
  public function queryQuoteAddress(Mage_Sales_Model_Quote_Address $mageQuoteAddress){
88
  return false;
89
  }
90
  //No caching allowed for order invoice
91
+ $responseResult = Mage::helper('speedtax/connector_speedtax')->batchVoidInvoices($invoiceNumbers);
92
 
93
  //Update status
94
  $batchVoidResults = json_decode($responseResult->data->result->batchVoidResults, 1);
130
  $mageQuoteItem->setTaxPercent (sprintf("%.4f", 100*$taxAmount/($mageQuoteItem->getRowTotal() - $mageQuoteItem->getDiscountAmount())));
131
  }
132
  }
133
+ $taxShippingAmount = $this->_getTaxShippingAmount($responseResult);
134
+ if(!!$taxShippingAmount){
135
  $mageQuoteAddress->setShippingTaxAmount($taxShippingAmount);
136
  $mageQuoteAddress->setBaseShippingTaxAmount($taxShippingAmount);
137
  }
167
  return 0.0;
168
  }
169
 
170
+ protected function _getTaxShippingAmount($responseResult) {
171
+ if(isset($responseResult->lineItemBundles->lineItems)){
172
+ foreach($responseResult->lineItemBundles->lineItems as $responseLineItem){
173
+ if($responseLineItem->productCode == Harapartners_SpeedTax_Helper_Connector_Data::TAX_SHIPPING_LINEITEM_TAX_CLASS){
174
+ return $responseLineItem->taxAmount->decimalValue;
175
+ }
176
+ }
177
+ }
178
  return 0.0;
179
  }
180
 
app/code/community/Harapartners/SpeedTax/Model/Failsafe/Calculation.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license [^]
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+ class Harapartners_SpeedTax_Model_Failsafe_Calculation extends Mage_Tax_Model_Calculation {
14
+
15
+ public function getRate($request)
16
+ {
17
+ if (!$request->getCountryId() || !$request->getRegionId() || !$request->getPostcode()) {
18
+ return 0;
19
+ }
20
+
21
+ //Ignore default non-taxable goods, product_class_id = 0 or missing
22
+ if(!$request->getData('product_class_id')){
23
+ return 0.0;
24
+ }
25
+
26
+ $failsafeCalRate = Mage::getModel('speedtax/failsafe_calculation_rate');
27
+ // Level 1: exact match
28
+ $failsafeCalRate->loadByCountryIdRegionIdPostcode($request->getCountryId(), $request->getRegionId(), $request->getPostcode());
29
+ if(!!$failsafeCalRate->getId() && !!$failsafeCalRate->getTaxRate()){
30
+ return $failsafeCalRate->getTaxRate();
31
+ }
32
+ // Level 2: partial match
33
+ $failsafeCalRate->loadByCountryIdRegionId($request->getCountryId(), $request->getRegionId());
34
+ if(!!$failsafeCalRate->getId() && !!$failsafeCalRate->getTaxRate()){
35
+ return $failsafeCalRate->getTaxRate();
36
+ }
37
+
38
+ // Default
39
+ return 0.0;
40
+ }
41
+
42
+ }
app/code/community/Harapartners/SpeedTax/Model/Failsafe/Calculation/Rate.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+
14
+ class Harapartners_SpeedTax_Model_Failsafe_Calculation_Rate extends Mage_Core_Model_Abstract {
15
+
16
+ protected function _construct() {
17
+ $this->_init('speedtax/failsafe_calculation_rate');
18
+ }
19
+
20
+ public function loadByCountryIdRegionIdPostcode($countryId, $regionId, $postcode){
21
+ $this->addData($this->getResource()->loadByCountryIdRegionIdPostcode($countryId, $regionId, $postcode));
22
+ return $this;
23
+ }
24
+
25
+ public function loadByCountryIdRegionId($countryId, $regionId){
26
+ $this->addData($this->getResource()->loadByCountryIdRegionId($countryId, $regionId));
27
+ return $this;
28
+ }
29
+
30
+ protected function _beforeSave(){
31
+ $datetime = date('Y-m-d H:i:s');
32
+ if(!$this->getId()){
33
+ $this->setData('created_at', $datetime);
34
+ }
35
+ $this->setData('updated_at', $datetime);
36
+ parent::_beforeSave();
37
+ }
38
+
39
+ }
app/code/community/Harapartners/SpeedTax/Model/Failsafe/Sales/Total/Quote/Tax.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license [^]
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+ class Harapartners_SpeedTax_Model_Failsafe_Sales_Total_Quote_Tax extends Mage_Tax_Model_Sales_Total_Quote_Tax {
14
+
15
+ public function __construct(){
16
+ parent::__construct();
17
+ $this->_calculator = Mage::getSingleton('speedtax/failsafe_calculation');
18
+ }
19
+
20
+ protected function _calculateShippingTax(Mage_Sales_Model_Quote_Address $address, $taxRateRequest){
21
+ if(!Mage::getStoreConfig("speedtax/speedtax/tax_shipping")){
22
+ return $this;
23
+ }
24
+ return parent::_calculateShippingTax($address, $taxRateRequest);
25
+ }
26
+
27
+ }
app/code/community/Harapartners/SpeedTax/Model/Observer.php CHANGED
@@ -14,22 +14,55 @@
14
 
15
  class Harapartners_SpeedTax_Model_Observer extends Mage_Core_Model_Abstract {
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  public function saleOrderInvoicePay(Varien_Event_Observer $observer) {
18
  if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
19
  return;
20
  }
21
  $invoice = $observer->getEvent()->getInvoice();
 
 
 
 
 
22
  try {
23
  $processor = Mage::helper('speedtax/processor');
24
  $responseResult = $processor->postOrderInvoice($invoice);
 
 
 
 
 
25
  } catch( Exception $e ) {
26
  //Suppress exception so that the transaction is not reverted (payment already processed)
27
- Mage::logException($e);
28
- $maskedErrorMessage = 'There is an error processing tax information.';
29
- Mage::getSingleton('core/session')->addError($maskedErrorMessage);
 
 
 
 
 
 
30
  }
31
  }
32
 
 
33
  public function salesOrderCreditmemoRefund(Varien_Event_Observer $observer) {
34
  if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
35
  return;
@@ -40,28 +73,92 @@ class Harapartners_SpeedTax_Model_Observer extends Mage_Core_Model_Abstract {
40
  $responseResult = $processor->postOrderCreditmemo($creditmemo);
41
  } catch( Exception $e ) {
42
  //Suppress exception so that the transaction is not reverted (payment already processed)
43
- Mage::logException($e);
44
- $maskedErrorMessage = 'There is an error processing tax information.';
45
- Mage::getSingleton('core/session')->addError($maskedErrorMessage);
 
 
 
 
46
  }
47
  }
48
 
49
- //For manual cancel or order edit related cancellation
50
  public function orderCancelAfter(Varien_Event_Observer $observer) {
51
- if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
52
- return;
53
- }
54
- $order = $observer->getEvent()->getOrder();
55
- try {
56
- $processor = Mage::helper('speedtax/processor');
57
- $responseResult = $processor->cancelAllOrderTransactions($order);
58
- } catch( Exception $e ) {
59
- //Suppress exception so that the transaction is not reverted (payment already processed)
60
- Mage::logException($e);
61
- $maskedErrorMessage = 'There is an error processing tax information.';
62
- Mage::getSingleton('core/session')->addError($maskedErrorMessage);
63
- }
 
 
 
 
 
64
  }
65
 
66
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
14
 
15
  class Harapartners_SpeedTax_Model_Observer extends Mage_Core_Model_Abstract {
16
 
17
+ // ============================== Checkout process, failsafe calculation can be enabled ============================== //
18
+ public function saleOrderSaveBefore(Varien_Event_Observer $observer) {
19
+ //Flag orders with speedtax failsafe calculation
20
+ if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
21
+ return;
22
+ }
23
+ $order = $observer->getEvent()->getOrder();
24
+ if (Mage::helper('speedtax')->isFailsafeEnabled()){
25
+ if(Mage::registry('is_speedtax_failsafe_calculation')){
26
+ $order->setData('is_speedtax_failsafe_calculation', 1);
27
+ Mage::unregister('is_speedtax_failsafe_calculation');
28
+ }
29
+ }
30
+ }
31
+
32
+ // ============================== Post invoices to SpeedTax (failsafe can be enabled) ============================== //
33
  public function saleOrderInvoicePay(Varien_Event_Observer $observer) {
34
  if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
35
  return;
36
  }
37
  $invoice = $observer->getEvent()->getInvoice();
38
+ if (Mage::helper('speedtax')->isFailsafeEnabled()){
39
+ if(!!$invoice->getOrder()){
40
+ $invoice->setData('is_speedtax_failsafe_calculation', $invoice->getOrder()->getData('is_speedtax_failsafe_calculation'));
41
+ }
42
+ }
43
  try {
44
  $processor = Mage::helper('speedtax/processor');
45
  $responseResult = $processor->postOrderInvoice($invoice);
46
+ if(isset($responseResult->totalTax->decimalValue)){
47
+ $baseSpeedTaxTaxAmount = $responseResult->totalTax->decimalValue;
48
+ $invoice->setData('base_speedtax_tax_amount', $baseSpeedTaxTaxAmount);
49
+ $invoice->setData('speedtax_tax_amount', Mage::app()->getStore()->convertPrice($baseSpeedTaxTaxAmount, false));
50
+ }
51
  } catch( Exception $e ) {
52
  //Suppress exception so that the transaction is not reverted (payment already processed)
53
+ //Mage::logException($e);
54
+ Mage::log("Cannot post order invoice: {$e->getMessage()}\r\n{$e->getTraceAsString()}", null, Harapartners_SpeedTax_Helper_Data::ERROR_LOG_FILE, true);
55
+ if (Mage::helper('speedtax')->isFailsafeEnabled()) {
56
+ //Failsafe logic: mark invoice for "post invoice failsafe"
57
+ $invoice->setData('speedtax_invoice_status', Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_FAILSAFE);
58
+ }else{
59
+ $maskedErrorMessage = 'There is an error processing tax information.';
60
+ Mage::getSingleton('core/session')->addError($maskedErrorMessage);
61
+ }
62
  }
63
  }
64
 
65
+ // ============================== Cancel invoices in SpeedTax ============================== //
66
  public function salesOrderCreditmemoRefund(Varien_Event_Observer $observer) {
67
  if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
68
  return;
73
  $responseResult = $processor->postOrderCreditmemo($creditmemo);
74
  } catch( Exception $e ) {
75
  //Suppress exception so that the transaction is not reverted (payment already processed)
76
+ //Mage::logException($e);
77
+ Mage::log("Cannot post order credit memo: {$e->getMessage()}\r\n{$e->getTraceAsString()}", null, Harapartners_SpeedTax_Helper_Data::ERROR_LOG_FILE, true);
78
+ $maskedErrorMessage = 'There is an error processing tax information for order credit memo.';
79
+
80
+ //This is backend only activity, do NOT suppress exceptions
81
+ //Mage::getSingleton('core/session')->addError($maskedErrorMessage);
82
+ Mage::throwException($maskedErrorMessage);
83
  }
84
  }
85
 
86
+ //Upon order cancel/edit, credit memo must be created manually for existing invoices, SpeedTax invoices will NOT be voided
87
  public function orderCancelAfter(Varien_Event_Observer $observer) {
88
+ return;
89
+ // if (!Mage::helper('speedtax')->isSpeedTaxEnabled()) {
90
+ // return;
91
+ // }
92
+ // $order = $observer->getEvent()->getOrder();
93
+ // try {
94
+ // $processor = Mage::helper('speedtax/processor');
95
+ // $responseResult = $processor->cancelAllOrderTransactions($order);
96
+ // } catch( Exception $e ) {
97
+ // //Suppress exception so that the transaction is not reverted (payment already processed)
98
+ // //Mage::logException($e);
99
+ // Mage::log("Cannot cancel all order transactions: {$e->getMessage()}\r\n{$e->getTraceAsString()}", null, Harapartners_SpeedTax_Helper_Data::ERROR_LOG_FILE, true);
100
+ // $maskedErrorMessage = 'There is an error processing tax information for all order transactions.';
101
+ //
102
+ // //This is backend only activity, do NOT suppress exceptions
103
+ // //Mage::getSingleton('core/session')->addError($maskedErrorMessage);
104
+ // Mage::throwException($maskedErrorMessage);
105
+ // }
106
  }
107
 
108
+ // ============================================================================================ //
109
+ // ---------------------------------------- Admin only ---------------------------------------- //
110
+ /**
111
+ * Prepare important admin panel messages, set data in session
112
+ *
113
+ * @param Varien_Event_Observer $observer
114
+ */
115
+ public function adminhtmlOnlyLayoutGenerateBlocksAfter(Varien_Event_Observer $observer){
116
+ $controllerAction = $observer->getEvent()->getData('action');
117
+ $layout = $observer->getEvent()->getData('layout');
118
+
119
+ //Only add message for administrator who already logged in
120
+ if(!!Mage::getSingleton('admin/session')->getUser() && !!Mage::getSingleton('admin/session')->getUser()->getId()){
121
+ $notificationsBlock = $layout->getBlock('notifications');
122
+ if(!!$notificationsBlock && !!($notificationsBlock instanceof Mage_Core_Block_Abstract)){
123
+ $nsNotificationBlock = $layout->createBlock('speedtax/adminhtml_notification');
124
+ $notificationsBlock->append($nsNotificationBlock, 'speedtax_notification');
125
+ }
126
+ }
127
+ return;
128
+ }
129
+
130
+ // ============================================================================================ //
131
+ // ---------------------------------------- CRON jobs ---------------------------------------- //
132
+ public function batchPostFailsafeInvoice(){
133
+ if(!Mage::getStoreConfig ( 'speedtax/failsafe/is_auto_post_failsafe_invoice' )){
134
+ return;
135
+ }
136
+ $sptxProcessor = Mage::helper('speedtax/processor');
137
+ $invoicCollection = Mage::getModel('sales/order_invoice')->getCollection();
138
+ $invoicCollection->addAttributeToFilter('speedtax_invoice_status', Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_FAILSAFE);
139
+ $invoicCollection->setPageSize(Harapartners_SpeedTax_Helper_Data::DEFAULT_MAGENTO_COLLECTION_PAGE_SIZE);
140
+ $currentPage = 1;
141
+ $totalNumPages = $invoicCollection->getLastPageNumber();
142
+ do {
143
+ $invoicCollection->setCurPage($currentPage);
144
+ foreach ($invoicCollection as $invoice) {
145
+ try{
146
+ $responseResult = $sptxProcessor->postOrderInvoice($invoice);
147
+ if(isset($responseResult->totalTax->decimalValue)){
148
+ $baseSpeedTaxTaxAmount = $responseResult->totalTax->decimalValue;
149
+ $invoice->setData('base_speedtax_tax_amount', $baseSpeedTaxTaxAmount);
150
+ $invoice->setData('speedtax_tax_amount', Mage::app()->getStore()->convertPrice($baseSpeedTaxTaxAmount, false));
151
+ $invoice->save();
152
+ }
153
+ }catch (Exception $ex){
154
+ //Suppress errors in cronjob
155
+ }
156
+ unset($invoice);
157
+ }
158
+ // Pagination Loop Control
159
+ $currentPage ++;
160
+ $invoicCollection->clear();
161
+ } while ($currentPage <= $totalNumPages);
162
+ }
163
+
164
  }
app/code/community/Harapartners/SpeedTax/Model/Resource/Failsafe/Calculation/Rate.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+
14
+ class Harapartners_SpeedTax_Model_Resource_Failsafe_Calculation_Rate extends Mage_Core_Model_Resource_Db_Abstract {
15
+
16
+ protected function _construct() {
17
+ $this->_init('speedtax/failsafe_calculation_rate', 'rate_id');
18
+ }
19
+
20
+ public function loadByCountryIdRegionIdPostcode($countryId, $regionId, $postcode){
21
+ $readAdapter = $this->_getReadAdapter();
22
+ $select = $readAdapter->select()
23
+ ->from($this->getMainTable())
24
+ ->where('country_id=:country_id')
25
+ ->where('region_id=:region_id')
26
+ ->where('postcode=:postcode');
27
+ $result = $readAdapter->fetchRow($select, array('country_id' => $countryId, 'region_id' => $regionId, 'postcode' => $postcode));
28
+ if (!$result) {
29
+ $result = array();
30
+ }
31
+ return $result;
32
+ }
33
+
34
+ public function loadByCountryIdRegionId($countryId, $regionId){
35
+ $readAdapter = $this->_getReadAdapter();
36
+ $select = $readAdapter->select()
37
+ ->from($this->getMainTable())
38
+ ->where('country_id=:country_id')
39
+ ->where('region_id=:region_id');
40
+ $result = $readAdapter->fetchRow($select, array('country_id' => $countryId, 'region_id' => $regionId));
41
+ if (!$result) {
42
+ $result = array();
43
+ }
44
+ return $result;
45
+ }
46
+
47
+ }
app/code/community/Harapartners/SpeedTax/Model/Resource/Failsafe/Calculation/Rate/Collection.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+
14
+ class Harapartners_SpeedTax_Model_Resource_Failsafe_Calculation_Rate_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract{
15
+
16
+ public function _construct(){
17
+ $this->_init('speedtax/failsafe_calculation_rate');
18
+ }
19
+
20
+ }
app/code/community/Harapartners/SpeedTax/Model/Rewrite/Tax/Sales/Total/Quote/Tax.php CHANGED
@@ -41,13 +41,27 @@ class Harapartners_SpeedTax_Model_Rewrite_Tax_Sales_Total_Quote_Tax extends Mage
41
  $taxAmount = $processor->getTotalTax($responseResult);
42
  $this->_addAmount(Mage::app()->getStore()->convertPrice($taxAmount, false));
43
  $this->_addBaseAmount($taxAmount);
 
 
 
 
44
  }
45
  } catch(Exception $e) {
46
  //Tax collecting is very important, this is within the collect total (cannot bubble exceptions), force a redirect
47
- Mage::logException($e);
48
- $maskedErrorMessage = 'There is an error calculating tax.';
49
- Mage::getSingleton('core/session')->addError($maskedErrorMessage);
50
- throw new Mage_Core_Model_Session_Exception($maskedErrorMessage); //Session exceptions will be redirected to base URL
 
 
 
 
 
 
 
 
 
 
51
  }
52
 
53
  return $this;
41
  $taxAmount = $processor->getTotalTax($responseResult);
42
  $this->_addAmount(Mage::app()->getStore()->convertPrice($taxAmount, false));
43
  $this->_addBaseAmount($taxAmount);
44
+ if (Mage::helper('speedtax')->isFailsafeEnabled()) {
45
+ //Failsafe logic: accumuate rates in preparation of future failure
46
+ Mage::helper('speedtax/failsafe')->updateFailsafeRate($address, $responseResult);
47
+ }
48
  }
49
  } catch(Exception $e) {
50
  //Tax collecting is very important, this is within the collect total (cannot bubble exceptions), force a redirect
51
+ //Mage::logException($e);
52
+ Mage::log("Cannot collect quote tax total: {$e->getMessage()}\r\n{$e->getTraceAsString()}", null, Harapartners_SpeedTax_Helper_Data::ERROR_LOG_FILE, true);
53
+ if (Mage::helper('speedtax')->isFailsafeEnabled()) {
54
+ //Failsafe logic: mark "calculate by failsafe rates" in case the order is placed
55
+ Mage::unregister('is_speedtax_failsafe_calculation');
56
+ Mage::register('is_speedtax_failsafe_calculation', true);
57
+ //Failsafe logic: calculate by failsafe rates
58
+ $taxFailsafe = Mage::getModel('speedtax/failsafe_sales_total_quote_tax');
59
+ return $taxFailsafe->collect($address);
60
+ }else{
61
+ $maskedErrorMessage = 'There is an error calculating tax.';
62
+ Mage::getSingleton('core/session')->addError($maskedErrorMessage);
63
+ throw new Mage_Core_Model_Session_Exception($maskedErrorMessage); //Session exceptions will be redirected to base URL
64
+ }
65
  }
66
 
67
  return $this;
app/code/community/Harapartners/SpeedTax/controllers/Adminhtml/InvoiceController.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Adminhtml_InvoiceController extends Mage_Adminhtml_Controller_Action {
14
+
15
+ public function indexAction() {
16
+ $this->loadLayout ();
17
+ $this->_setActiveMenu ( 'speedtax/invoice' );
18
+ $this->_addContent ( $this->getLayout ()->createBlock ( 'speedtax/adminhtml_invoice_all_index' ) );
19
+ $this->renderLayout ();
20
+ }
21
+
22
+ public function failsafeIndexAction() {
23
+ $this->loadLayout ();
24
+ $this->_setActiveMenu ( 'speedtax/invoice' );
25
+ $this->_addContent ( $this->getLayout ()->createBlock ( 'speedtax/adminhtml_invoice_failsafe_index' ) );
26
+ $this->renderLayout ();
27
+ }
28
+
29
+ public function rateVerificationIndexAction() {
30
+ $this->loadLayout ();
31
+ $this->_setActiveMenu ( 'speedtax/invoice' );
32
+ $this->_addContent ( $this->getLayout ()->createBlock ( 'speedtax/adminhtml_invoice_rateverification_index' ) );
33
+ $this->renderLayout ();
34
+ }
35
+
36
+ public function massPostToSpeedtaxAction(){
37
+ $invoiceIds = $this->getRequest()->getPost('invoice_ids', array());
38
+ $sptxProcessor = Mage::helper('speedtax/processor');
39
+ $successInvoiceIds = array();
40
+ $noticeInvoiceIds = array();
41
+ $errorInvoiceIds = array();
42
+ $allowedInovicePostStatusArray = array(
43
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_PENDING,
44
+ Harapartners_SpeedTax_Helper_Processor::SPEEDTAX_INVOICE_STATUS_FAILSAFE
45
+ );
46
+ foreach ($invoiceIds as $invoiceId) {
47
+ $invoice = Mage::getModel('sales/order_invoice')->load($invoiceId);
48
+ if(!in_array($invoice->getData('speedtax_invoice_status'), $allowedInovicePostStatusArray)){
49
+ $noticeInvoiceIds[] = $invoice->getData('increment_id');
50
+ continue;
51
+ }
52
+ try{
53
+ $responseResult = $sptxProcessor->postOrderInvoice($invoice);
54
+ if(isset($responseResult->totalTax->decimalValue)){
55
+ $baseSpeedTaxTaxAmount = $responseResult->totalTax->decimalValue;
56
+ $invoice->setData('base_speedtax_tax_amount', $baseSpeedTaxTaxAmount);
57
+ $invoice->setData('speedtax_tax_amount', Mage::app()->getStore()->convertPrice($baseSpeedTaxTaxAmount, false));
58
+ $invoice->save();
59
+ }
60
+ $successInvoiceIds[] = $invoice->getData('increment_id');
61
+ }catch (Exception $ex){
62
+ $errorInvoiceIds[] = $invoice->getData('increment_id');
63
+ }
64
+ unset($invoice);
65
+ }
66
+
67
+ if(count($successInvoiceIds)){
68
+ Mage::getSingleton('adminhtml/session')->addSuccess("Invoice posted to SalesTax. Invoice #" . implode(", #", $successInvoiceIds));
69
+ }
70
+ if(count($noticeInvoiceIds)){
71
+ Mage::getSingleton('adminhtml/session')->addNotice("Only inovices with Failsafe or Pending status can be posted. Invoice #" . implode(", #", $noticeInvoiceIds));
72
+ }
73
+ if(count($errorInvoiceIds)){
74
+ Mage::getSingleton('adminhtml/session')->addError("Cannot post invoices to SalesTax. Invoice: #" . implode(", #", $errorInvoiceIds));
75
+ }
76
+
77
+ $this->_redirectReferer();
78
+ }
79
+
80
+ }
app/code/community/Harapartners/SpeedTax/controllers/Adminhtml/NotificationController.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ */
12
+
13
+ class Harapartners_SpeedTax_Adminhtml_NotificationController extends Mage_Adminhtml_Controller_Action {
14
+
15
+ public function disableAction() {
16
+ try{
17
+ $notificationkey = $this->getRequest()->getParam('notification_key');
18
+ $coreConfigData = Mage::getModel('core/config_data')->load(Harapartners_SpeedTax_Helper_Data::XML_PATH_NOTIFICATION_DISABLED_COMPRESS, 'path');
19
+ //In case the first time save
20
+ $coreConfigData->setpath(Harapartners_SpeedTax_Helper_Data::XML_PATH_NOTIFICATION_DISABLED_COMPRESS);
21
+ $notificationDisabled = json_decode($coreConfigData->getValue(), 1);
22
+ $notificationDisabled[$notificationkey] = 1;
23
+ $coreConfigData->setValue(json_encode($notificationDisabled));
24
+ $coreConfigData->save();
25
+ }catch (Exception $ex){
26
+ //Silence
27
+ }
28
+ $this->_redirectReferer();
29
+ }
30
+
31
+
32
+ }
app/code/community/Harapartners/SpeedTax/controllers/Adminhtml/System/Config/AjaxController.php CHANGED
@@ -55,7 +55,7 @@ class Harapartners_SpeedTax_Adminhtml_System_Config_AjaxController extends Mage_
55
  //Need to send $websiteResultJson, the store config is still the cache value, not our new value
56
  echo json_encode(array(
57
  'status' => 1,
58
- 'message' => 'Successful! Please save your configuration'
59
  )); //Json success
60
  exit;
61
  }
55
  //Need to send $websiteResultJson, the store config is still the cache value, not our new value
56
  echo json_encode(array(
57
  'status' => 1,
58
+ 'message' => 'Validation successful!'
59
  )); //Json success
60
  exit;
61
  }
app/code/community/Harapartners/SpeedTax/etc/adminhtml.xml ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ *
13
+ -->
14
+ <config>
15
+ <acl>
16
+ <resources>
17
+ <admin>
18
+ <children>
19
+ <speedtax translate="title" module="speedtax">
20
+ <title>SalesTax</title>
21
+ <children>
22
+ <invoice>
23
+ <title>Manage Invoices</title>
24
+ </invoice>
25
+ </children>
26
+ </speedtax>
27
+ <system>
28
+ <children>
29
+ <config>
30
+ <children>
31
+ <speedtax translate="title" module="speedtax">
32
+ <title>SpeedTax Configuration</title>
33
+ </speedtax>
34
+ </children>
35
+ </config>
36
+ </children>
37
+ </system>
38
+ </children>
39
+ </admin>
40
+ </resources>
41
+ </acl>
42
+ <menu>
43
+ <speedtax translate="title" module="speedtax">
44
+ <title>SalesTax</title>
45
+ <sort_order>900</sort_order>
46
+ <children>
47
+ <!-- Core -->
48
+ <config translate="title" module="speedtax">
49
+ <title>SalesTax Config</title>
50
+ <sort_order>10</sort_order>
51
+ <action>adminhtml/system_config/edit/section/speedtax</action>
52
+ </config>
53
+ <invoice_index translate="title" module="speedtax">
54
+ <title>All Invoices</title>
55
+ <sort_order>100</sort_order>
56
+ <action>speedtax_adminhtml/invoice/index</action>
57
+ </invoice_index>
58
+ <invoice_failsafe_index translate="title" module="speedtax">
59
+ <title>Failsafe Invoices</title>
60
+ <sort_order>200</sort_order>
61
+ <action>speedtax_adminhtml/invoice/failsafeIndex</action>
62
+ </invoice_failsafe_index>
63
+ <invoice_ratevalidation_index translate="title" module="speedtax">
64
+ <title>Failsafe Rate Verification</title>
65
+ <sort_order>300</sort_order>
66
+ <action>speedtax_adminhtml/invoice/rateVerificationIndex</action>
67
+ </invoice_ratevalidation_index>
68
+ </children>
69
+ </speedtax>
70
+ </menu>
71
+ </config>
app/code/community/Harapartners/SpeedTax/etc/config.xml CHANGED
@@ -15,7 +15,7 @@
15
  <config>
16
  <modules>
17
  <Harapartners_SpeedTax>
18
- <version>3.1.6</version>
19
  </Harapartners_SpeedTax>
20
  </modules>
21
  <global>
@@ -27,7 +27,16 @@
27
  <models>
28
  <speedtax>
29
  <class>Harapartners_SpeedTax_Model</class>
 
30
  </speedtax>
 
 
 
 
 
 
 
 
31
  <tax>
32
  <rewrite>
33
  <sales_total_quote_tax>Harapartners_SpeedTax_Model_Rewrite_Tax_Sales_Total_Quote_Tax</sales_total_quote_tax>
@@ -50,6 +59,18 @@
50
  </speedtax_setup>
51
  </resources>
52
  <events>
 
 
 
 
 
 
 
 
 
 
 
 
53
  <sales_order_invoice_pay>
54
  <observers>
55
  <speedtax>
@@ -59,6 +80,8 @@
59
  </speedtax>
60
  </observers>
61
  </sales_order_invoice_pay>
 
 
62
  <sales_order_creditmemo_refund>
63
  <observers>
64
  <speedtax>
@@ -68,7 +91,9 @@
68
  </speedtax>
69
  </observers>
70
  </sales_order_creditmemo_refund>
71
- <order_cancel_after>
 
 
72
  <observers>
73
  <speedtax>
74
  <type>singleton</type>
@@ -76,30 +101,24 @@
76
  <method>orderCancelAfter</method>
77
  </speedtax>
78
  </observers>
79
- </order_cancel_after>
80
  </events>
81
  </global>
82
  <adminhtml>
83
- <acl>
84
- <resources>
85
- <admin>
86
- <children>
87
- <system>
88
- <children>
89
- <config>
90
- <children>
91
- <speedtax translate="title" module="speedtax">
92
- <title>SpeedTax Configuration</title>
93
- </speedtax>
94
- </children>
95
- </config>
96
- </children>
97
- </system>
98
- </children>
99
- </admin>
100
- </resources>
101
- </acl>
102
- </adminhtml>
103
  <admin>
104
  <routers>
105
  <speedtax_adminhtml>
@@ -111,6 +130,18 @@
111
  </speedtax_adminhtml>
112
  </routers>
113
  </admin>
 
 
 
 
 
 
 
 
 
 
 
 
114
  <default>
115
  <speedtax>
116
  <speedtax>
@@ -125,8 +156,12 @@
125
  <error_frontend_message>Unfortunately, we could not calculate tax for your order. Please try again with a different address or contact us to complete your order.</error_frontend_message>
126
  <error_backend_message>There was an error getting tax rates from Speedtax. Please see the error log for details.</error_backend_message>
127
  <error_notification_toolbar>1</error_notification_toolbar>
128
- <onepage_normalize_message>Your shipping address has been modified during our validation process. Please confirm the address to the right is accurate.</onepage_normalize_message>
129
  </speedtax>
 
 
 
 
130
  </speedtax>
131
  </default>
132
- </config>
15
  <config>
16
  <modules>
17
  <Harapartners_SpeedTax>
18
+ <version>4.1.0</version>
19
  </Harapartners_SpeedTax>
20
  </modules>
21
  <global>
27
  <models>
28
  <speedtax>
29
  <class>Harapartners_SpeedTax_Model</class>
30
+ <resourceModel>speedtax_resource</resourceModel>
31
  </speedtax>
32
+ <speedtax_resource>
33
+ <class>Harapartners_SpeedTax_Model_Resource</class>
34
+ <entities>
35
+ <failsafe_calculation_rate>
36
+ <table>speedtax_failsafe_calculation_rate</table>
37
+ </failsafe_calculation_rate>
38
+ </entities>
39
+ </speedtax_resource>
40
  <tax>
41
  <rewrite>
42
  <sales_total_quote_tax>Harapartners_SpeedTax_Model_Rewrite_Tax_Sales_Total_Quote_Tax</sales_total_quote_tax>
59
  </speedtax_setup>
60
  </resources>
61
  <events>
62
+ <!-- Checkout process, (failsafe calculation can be enabled) -->
63
+ <sales_order_save_before>
64
+ <observers>
65
+ <speedtax>
66
+ <type>singleton</type>
67
+ <class>speedtax/observer</class>
68
+ <method>saleOrderSaveBefore</method>
69
+ </speedtax>
70
+ </observers>
71
+ </sales_order_save_before>
72
+
73
+ <!-- Post invoices to SpeedTax (failsafe delayed invoice post can be enabled) -->
74
  <sales_order_invoice_pay>
75
  <observers>
76
  <speedtax>
80
  </speedtax>
81
  </observers>
82
  </sales_order_invoice_pay>
83
+
84
+ <!-- Post credit memo to SpeedTax (admin only function, no failsafe needed) -->
85
  <sales_order_creditmemo_refund>
86
  <observers>
87
  <speedtax>
91
  </speedtax>
92
  </observers>
93
  </sales_order_creditmemo_refund>
94
+
95
+ <!-- Upon order cancel/edit, credit memo must be created manually for existing invoices, SpeedTax invoices will NOT be voided -->
96
+ <!--order_cancel_after>
97
  <observers>
98
  <speedtax>
99
  <type>singleton</type>
101
  <method>orderCancelAfter</method>
102
  </speedtax>
103
  </observers>
104
+ </order_cancel_after-->
105
  </events>
106
  </global>
107
  <adminhtml>
108
+ <events>
109
+ <controller_action_layout_generate_blocks_after>
110
+ <!-- Global layout modifications -->
111
+ <!-- Prepare and render important admin panel messages -->
112
+ <observers>
113
+ <speedtax_adminhtml_only_layout_generate_blocks_after>
114
+ <type>singleton</type>
115
+ <class>speedtax/observer</class>
116
+ <method>adminhtmlOnlyLayoutGenerateBlocksAfter</method>
117
+ </speedtax_adminhtml_only_layout_generate_blocks_after>
118
+ </observers>
119
+ </controller_action_layout_generate_blocks_after>
120
+ </events>
121
+ </adminhtml>
 
 
 
 
 
 
122
  <admin>
123
  <routers>
124
  <speedtax_adminhtml>
130
  </speedtax_adminhtml>
131
  </routers>
132
  </admin>
133
+ <crontab>
134
+ <jobs>
135
+ <speedtax_batch_post_failsafe_invoice>
136
+ <schedule>
137
+ <cron_expr>23 * * * *</cron_expr>
138
+ </schedule>
139
+ <run>
140
+ <model>speedtax/observer::batchPostFailsafeInvoice</model>
141
+ </run>
142
+ </speedtax_batch_post_failsafe_invoice>
143
+ </jobs>
144
+ </crontab>
145
  <default>
146
  <speedtax>
147
  <speedtax>
156
  <error_frontend_message>Unfortunately, we could not calculate tax for your order. Please try again with a different address or contact us to complete your order.</error_frontend_message>
157
  <error_backend_message>There was an error getting tax rates from Speedtax. Please see the error log for details.</error_backend_message>
158
  <error_notification_toolbar>1</error_notification_toolbar>
159
+ <onepage_normalize_message>Your shipping address has been modified during our validation process. Please confirm the address to the right is accurate.</onepage_normalize_message>
160
  </speedtax>
161
+ <failsafe>
162
+ <is_enabled>1</is_enabled>
163
+ <is_auto_post_failsafe_invoice>1</is_auto_post_failsafe_invoice>
164
+ </failsafe>
165
  </speedtax>
166
  </default>
167
+ </config>
app/code/community/Harapartners/SpeedTax/etc/system.xml CHANGED
@@ -22,7 +22,7 @@
22
  <sort_order>304</sort_order>
23
  <show_in_default>1</show_in_default>
24
  <show_in_website>1</show_in_website>
25
- <show_in_store>1</show_in_store>
26
  <groups>
27
  <signup>
28
  <label>Sign up for SalesTax.com</label>
@@ -36,15 +36,15 @@
36
  <sort_order>0</sort_order>
37
  <show_in_default>1</show_in_default>
38
  <show_in_website>1</show_in_website>
39
- <show_in_store>1</show_in_store>
40
  <expanded>1</expanded>
41
  </signup>
42
  <speedtax>
43
  <label>SalesTax.com Configuration</label>
44
- <sort_order>0</sort_order>
45
  <show_in_default>1</show_in_default>
46
  <show_in_website>1</show_in_website>
47
- <show_in_store>1</show_in_store>
48
  <fields>
49
  <is_enabled translate="label">
50
  <label>Status</label>
@@ -54,7 +54,7 @@
54
  <sort_order>100</sort_order>
55
  <show_in_default>1</show_in_default>
56
  <show_in_website>1</show_in_website>
57
- <show_in_store>1</show_in_store>
58
  </is_enabled>
59
  <username translate="label">
60
  <label>Username</label>
@@ -63,7 +63,7 @@
63
  <sort_order>110</sort_order>
64
  <show_in_default>1</show_in_default>
65
  <show_in_website>1</show_in_website>
66
- <show_in_store>1</show_in_store>
67
  <validate>required-entry</validate>
68
  </username>
69
  <password translate="label">
@@ -74,7 +74,7 @@
74
  <sort_order>115</sort_order>
75
  <show_in_default>1</show_in_default>
76
  <show_in_website>1</show_in_website>
77
- <show_in_store>1</show_in_store>
78
  <validate>required-entry</validate>
79
  </password>
80
  <company_code translate="label">
@@ -84,7 +84,7 @@
84
  <sort_order>120</sort_order>
85
  <show_in_default>1</show_in_default>
86
  <show_in_website>1</show_in_website>
87
- <show_in_store>1</show_in_store>
88
  <validate>required-entry</validate>
89
  </company_code>
90
  <is_test_mode translate="label">
@@ -95,11 +95,11 @@
95
  <sort_order>125</sort_order>
96
  <show_in_default>1</show_in_default>
97
  <show_in_website>1</show_in_website>
98
- <show_in_store>1</show_in_store>
99
  </is_test_mode>
100
  <authentication_wizard translate="button_label">
101
  <label></label>
102
- <comment><![CDATA[You <b style="color: red;">must</b> validate your login credentials first and then <b style="color: red;">save</b> the configuration.]]></comment>
103
  <button_label>Validate login credentials</button_label>
104
  <frontend_model>speedtax/adminhtml_system_config_form_field_authentication</frontend_model>
105
  <sort_order>150</sort_order>
@@ -115,7 +115,7 @@
115
  <sort_order>311</sort_order>
116
  <show_in_default>1</show_in_default>
117
  <show_in_website>1</show_in_website>
118
- <show_in_store>1</show_in_store>
119
  </tax_shipping>
120
  <origins translate="label">
121
  <label>Nexus</label>
@@ -128,8 +128,59 @@
128
  <show_in_store>0</show_in_store>
129
  <validate>required-entry</validate>
130
  </origins>
 
 
 
 
 
 
 
 
 
 
131
  </fields>
132
  </speedtax>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  <help_extra>
134
  <label>SalesTax.com Help</label>
135
  <comment><![CDATA[
@@ -139,10 +190,10 @@
139
  Learn more about the SalesTax.com solution, additional features, updates and help at <a href="http://www.harapartners.com/salestax" target="_blank" style="color: #00C3FF;">http://www.harapartners.com/salestax</a>.
140
  </p>
141
  ]]></comment>
142
- <sort_order>100</sort_order>
143
  <show_in_default>1</show_in_default>
144
  <show_in_website>1</show_in_website>
145
- <show_in_store>1</show_in_store>
146
  <expanded>1</expanded>
147
  </help_extra>
148
  </groups>
@@ -157,7 +208,7 @@
157
  <sort_order>99</sort_order>
158
  <show_in_default>1</show_in_default>
159
  <show_in_website>1</show_in_website>
160
- <show_in_store>1</show_in_store>
161
  </street>
162
  </fields>
163
  </origin>
22
  <sort_order>304</sort_order>
23
  <show_in_default>1</show_in_default>
24
  <show_in_website>1</show_in_website>
25
+ <show_in_store>0</show_in_store>
26
  <groups>
27
  <signup>
28
  <label>Sign up for SalesTax.com</label>
36
  <sort_order>0</sort_order>
37
  <show_in_default>1</show_in_default>
38
  <show_in_website>1</show_in_website>
39
+ <show_in_store>0</show_in_store>
40
  <expanded>1</expanded>
41
  </signup>
42
  <speedtax>
43
  <label>SalesTax.com Configuration</label>
44
+ <sort_order>100</sort_order>
45
  <show_in_default>1</show_in_default>
46
  <show_in_website>1</show_in_website>
47
+ <show_in_store>0</show_in_store>
48
  <fields>
49
  <is_enabled translate="label">
50
  <label>Status</label>
54
  <sort_order>100</sort_order>
55
  <show_in_default>1</show_in_default>
56
  <show_in_website>1</show_in_website>
57
+ <show_in_store>0</show_in_store>
58
  </is_enabled>
59
  <username translate="label">
60
  <label>Username</label>
63
  <sort_order>110</sort_order>
64
  <show_in_default>1</show_in_default>
65
  <show_in_website>1</show_in_website>
66
+ <show_in_store>0</show_in_store>
67
  <validate>required-entry</validate>
68
  </username>
69
  <password translate="label">
74
  <sort_order>115</sort_order>
75
  <show_in_default>1</show_in_default>
76
  <show_in_website>1</show_in_website>
77
+ <show_in_store>0</show_in_store>
78
  <validate>required-entry</validate>
79
  </password>
80
  <company_code translate="label">
84
  <sort_order>120</sort_order>
85
  <show_in_default>1</show_in_default>
86
  <show_in_website>1</show_in_website>
87
+ <show_in_store>0</show_in_store>
88
  <validate>required-entry</validate>
89
  </company_code>
90
  <is_test_mode translate="label">
95
  <sort_order>125</sort_order>
96
  <show_in_default>1</show_in_default>
97
  <show_in_website>1</show_in_website>
98
+ <show_in_store>0</show_in_store>
99
  </is_test_mode>
100
  <authentication_wizard translate="button_label">
101
  <label></label>
102
+ <comment><![CDATA[Please <b style="color: red;">save</b> the configuration after validating your login credentials.]]></comment>
103
  <button_label>Validate login credentials</button_label>
104
  <frontend_model>speedtax/adminhtml_system_config_form_field_authentication</frontend_model>
105
  <sort_order>150</sort_order>
115
  <sort_order>311</sort_order>
116
  <show_in_default>1</show_in_default>
117
  <show_in_website>1</show_in_website>
118
+ <show_in_store>0</show_in_store>
119
  </tax_shipping>
120
  <origins translate="label">
121
  <label>Nexus</label>
128
  <show_in_store>0</show_in_store>
129
  <validate>required-entry</validate>
130
  </origins>
131
+ <is_debug_transaction translate="label">
132
+ <label>Debug transactions</label>
133
+ <comment><![CDATA[If "Yes", transactions will be logged.]]></comment>
134
+ <frontend_type>select</frontend_type>
135
+ <source_model>adminhtml/system_config_source_yesno</source_model>
136
+ <sort_order>900</sort_order>
137
+ <show_in_default>1</show_in_default>
138
+ <show_in_website>1</show_in_website>
139
+ <show_in_store>0</show_in_store>
140
+ </is_debug_transaction>
141
  </fields>
142
  </speedtax>
143
+ <failsafe>
144
+ <label>Fail Safe Configuration</label>
145
+ <comment><![CDATA[
146
+ <p class="switcher">
147
+ Fail safe logic provides an additional layer of robustness to the tax integration.<br/>
148
+ This mechanism allows the customer to complete checkout in case the SalesTax service is unreachable.<br/>
149
+ Magento processes supported for fail safe: checkout, place order and invoice pay.<br/>
150
+ 1) During tax calculation, state level tax rates for default taxable goods are stored in Magento in case of a future failure.<br/>
151
+ 2) If the invoice cannot be posted to SalesTax, the invoice processing workflow can continue. The problematic invoices can be posted to SalesTax later.
152
+ </p>
153
+ ]]></comment>
154
+ <sort_order>200</sort_order>
155
+ <show_in_default>1</show_in_default>
156
+ <show_in_website>1</show_in_website>
157
+ <show_in_store>0</show_in_store>
158
+ <fields>
159
+ <is_enabled translate="label">
160
+ <label>Is Enabled</label>
161
+ <comment><![CDATA[]]></comment>
162
+ <frontend_type>select</frontend_type>
163
+ <source_model>adminhtml/system_config_source_yesno</source_model>
164
+ <sort_order>100</sort_order>
165
+ <show_in_default>1</show_in_default>
166
+ <show_in_website>1</show_in_website>
167
+ <show_in_store>0</show_in_store>
168
+ </is_enabled>
169
+ <is_auto_post_failsafe_invoice translate="label">
170
+ <label>Auto Post Fail Safe Invoice</label>
171
+ <comment><![CDATA[
172
+ If "Yes", fail safe invoice can be posted to SalesTax automatically.<br/>
173
+ Please make sure Magento cron job is running.
174
+ ]]></comment>
175
+ <frontend_type>select</frontend_type>
176
+ <source_model>adminhtml/system_config_source_yesno</source_model>
177
+ <sort_order>200</sort_order>
178
+ <show_in_default>1</show_in_default>
179
+ <show_in_website>1</show_in_website>
180
+ <show_in_store>0</show_in_store>
181
+ </is_auto_post_failsafe_invoice>
182
+ </fields>
183
+ </failsafe>
184
  <help_extra>
185
  <label>SalesTax.com Help</label>
186
  <comment><![CDATA[
190
  Learn more about the SalesTax.com solution, additional features, updates and help at <a href="http://www.harapartners.com/salestax" target="_blank" style="color: #00C3FF;">http://www.harapartners.com/salestax</a>.
191
  </p>
192
  ]]></comment>
193
+ <sort_order>300</sort_order>
194
  <show_in_default>1</show_in_default>
195
  <show_in_website>1</show_in_website>
196
+ <show_in_store>0</show_in_store>
197
  <expanded>1</expanded>
198
  </help_extra>
199
  </groups>
208
  <sort_order>99</sort_order>
209
  <show_in_default>1</show_in_default>
210
  <show_in_website>1</show_in_website>
211
+ <show_in_store>0</show_in_store>
212
  </street>
213
  </fields>
214
  </origin>
app/code/community/Harapartners/SpeedTax/sql/speedtax_setup/mysql4-upgrade-3.0.9-3.1.0.php CHANGED
@@ -13,114 +13,38 @@
13
  $installer = $this;
14
  $installer->startSetup();
15
 
16
- $speedTaxTransactionIdColumnName = 'speedtax_transaction_id';
17
- $speedtaxInvoiceNumberColumnName = 'speedtax_invoice_number';
18
- $speedtaxInvoiceStatusColumnName = 'speedtax_invoice_status';
19
- $connectionConfig = $installer->getConnection()->getConfig();
20
-
21
  // ================ Invoice ================ //
22
- $testQuery = "
23
- SELECT * FROM information_schema.COLUMNS
24
- WHERE column_name='$speedtaxInvoiceNumberColumnName'
25
- AND table_name='{$this->getTable('sales/invoice')}'
26
- AND table_schema='{$connectionConfig['dbname']}'
27
- ";
28
- if(!!$installer->getConnection()->fetchAll($testQuery)){
29
- $installer->run("
30
- ALTER TABLE `{$this->getTable('sales/invoice')}`
31
- DROP COLUMN `$speedtaxInvoiceNumberColumnName`;
32
- ");
33
- }
34
- $installer->run("
35
- ALTER TABLE `{$this->getTable('sales/invoice')}`
36
- ADD COLUMN `$speedtaxInvoiceNumberColumnName` varchar(255);
37
- ");
38
-
39
- $testQuery = "
40
- SELECT * FROM information_schema.COLUMNS
41
- WHERE column_name='$speedtaxInvoiceStatusColumnName'
42
- AND table_name='{$this->getTable('sales/invoice')}'
43
- AND table_schema='{$connectionConfig['dbname']}'
44
- ";
45
- if(!!$installer->getConnection()->fetchAll($testQuery)){
46
- $installer->run("
47
- ALTER TABLE `{$this->getTable('sales/invoice')}`
48
- DROP COLUMN `$speedtaxInvoiceStatusColumnName`;
49
- ");
50
- }
51
- $installer->run("
52
- ALTER TABLE `{$this->getTable('sales/invoice')}`
53
- ADD COLUMN `$speedtaxInvoiceStatusColumnName` SMALLINT(5) DEFAULT 0;
54
- ");
55
-
56
- $testQuery = "
57
- SELECT * FROM information_schema.COLUMNS
58
- WHERE column_name='$speedTaxTransactionIdColumnName'
59
- AND table_name='{$this->getTable('sales/invoice')}'
60
- AND table_schema='{$connectionConfig['dbname']}'
61
- ";
62
- if(!!$installer->getConnection()->fetchAll($testQuery)){
63
- $installer->run("
64
- ALTER TABLE `{$this->getTable('sales/invoice')}`
65
- DROP COLUMN `$speedTaxTransactionIdColumnName`;
66
- ");
67
- }
68
- $installer->run("
69
- ALTER TABLE `{$this->getTable('sales/invoice')}`
70
- ADD COLUMN `$speedTaxTransactionIdColumnName` varchar(255);
71
- ");
72
 
73
-
74
  // ================ Credit Memo ================ //
75
- $testQuery = "
76
- SELECT * FROM information_schema.COLUMNS
77
- WHERE column_name='$speedtaxInvoiceNumberColumnName'
78
- AND table_name='{$this->getTable('sales/creditmemo')}'
79
- AND table_schema='{$connectionConfig['dbname']}'
80
- ";
81
- if(!!$installer->getConnection()->fetchAll($testQuery)){
82
- $installer->run("
83
- ALTER TABLE `{$this->getTable('sales/creditmemo')}`
84
- DROP COLUMN `$speedtaxInvoiceNumberColumnName`;
85
- ");
86
- }
87
- $installer->run("
88
- ALTER TABLE `{$this->getTable('sales/creditmemo')}`
89
- ADD COLUMN `$speedtaxInvoiceNumberColumnName` varchar(255);
90
- ");
91
-
92
- $testQuery = "
93
- SELECT * FROM information_schema.COLUMNS
94
- WHERE column_name='$speedtaxInvoiceStatusColumnName'
95
- AND table_name='{$this->getTable('sales/creditmemo')}'
96
- AND table_schema='{$connectionConfig['dbname']}'
97
- ";
98
- if(!!$installer->getConnection()->fetchAll($testQuery)){
99
- $installer->run("
100
- ALTER TABLE `{$this->getTable('sales/creditmemo')}`
101
- DROP COLUMN `$speedtaxInvoiceStatusColumnName`;
102
- ");
103
- }
104
- $installer->run("
105
- ALTER TABLE `{$this->getTable('sales/creditmemo')}`
106
- ADD COLUMN `$speedtaxInvoiceStatusColumnName` SMALLINT(5) DEFAULT 0;
107
- ");
108
-
109
- $testQuery = "
110
- SELECT * FROM information_schema.COLUMNS
111
- WHERE column_name='$speedTaxTransactionIdColumnName'
112
- AND table_name='{$this->getTable('sales/creditmemo')}'
113
- AND table_schema='{$connectionConfig['dbname']}'
114
- ";
115
- if(!!$installer->getConnection()->fetchAll($testQuery)){
116
- $installer->run("
117
- ALTER TABLE `{$this->getTable('sales/creditmemo')}`
118
- DROP COLUMN `$speedTaxTransactionIdColumnName`;
119
- ");
120
- }
121
- $installer->run("
122
- ALTER TABLE `{$this->getTable('sales/creditmemo')}`
123
- ADD COLUMN `$speedTaxTransactionIdColumnName` varchar(255);
124
- ");
125
 
126
- $installer->endSetup();
13
  $installer = $this;
14
  $installer->startSetup();
15
 
 
 
 
 
 
16
  // ================ Invoice ================ //
17
+ $installer->getConnection()->addColumn(
18
+ $installer->getTable('sales/invoice'),
19
+ "speedtax_invoice_number",
20
+ "VARCHAR(255) COMMENT 'SpeedTax Invoice Number'"
21
+ );
22
+ $installer->getConnection()->addColumn(
23
+ $installer->getTable('sales/invoice'),
24
+ "speedtax_invoice_status",
25
+ "SMALLINT(5) DEFAULT '0' COMMENT 'SpeedTax Invoice Status'"
26
+ );
27
+ $installer->getConnection()->addColumn(
28
+ $installer->getTable('sales/invoice'),
29
+ "speedtax_transaction_id",
30
+ "VARCHAR(255) COMMENT 'SpeedTax Transaction ID'"
31
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
 
33
  // ================ Credit Memo ================ //
34
+ $installer->getConnection()->addColumn(
35
+ $installer->getTable('sales/creditmemo'),
36
+ "speedtax_invoice_number",
37
+ "VARCHAR(255) COMMENT 'SpeedTax Invoice Number'"
38
+ );
39
+ $installer->getConnection()->addColumn(
40
+ $installer->getTable('sales/creditmemo'),
41
+ "speedtax_invoice_status",
42
+ "SMALLINT(5) DEFAULT '0' COMMENT 'SpeedTax Invoice Status'"
43
+ );
44
+ $installer->getConnection()->addColumn(
45
+ $installer->getTable('sales/creditmemo'),
46
+ "speedtax_transaction_id",
47
+ "VARCHAR(255) COMMENT 'SpeedTax Transaction ID'"
48
+ );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ $installer->endSetup();
app/code/community/Harapartners/SpeedTax/sql/speedtax_setup/mysql4-upgrade-3.9.9-4.0.0.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * NOTICE OF LICENSE
4
+ *
5
+ * This source file is subject to the End User Software Agreement (EULA).
6
+ * It is also available through the world-wide-web at this URL:
7
+ * http://www.harapartners.com/license [^]
8
+ * If you did not receive a copy of the license and are unable to
9
+ * obtain it through the world-wide-web, please send an email
10
+ * to eula@harapartners.com so we can send you a copy immediately.
11
+ *
12
+ */
13
+ $installer = $this;
14
+ $installer->startSetup();
15
+
16
+ // ================= Calculation Table ================= //
17
+ $calculationTable = $installer->getConnection()
18
+ ->newTable($installer->getTable('speedtax/failsafe_calculation_rate'))
19
+ ->addColumn('rate_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
20
+ 'identity' => true,
21
+ 'unsigned' => true,
22
+ 'nullable' => false,
23
+ 'primary' => true,
24
+ ), 'Auto Increment Calculation Rate ID')
25
+ ->addColumn('country_id', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
26
+ 'nullable' => true,
27
+ ), 'Country ID')
28
+ ->addColumn('region_id', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
29
+ 'nullable' => true,
30
+ ), 'Region ID')
31
+ ->addColumn('postcode', Varien_Db_Ddl_Table::TYPE_VARCHAR, 255, array(
32
+ 'nullable' => true,
33
+ ), 'Postcode')
34
+ ->addColumn('customer_class_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
35
+ 'unsigned' => true,
36
+ 'nullable' => true,
37
+ ), 'Customer Class ID')
38
+ ->addColumn('product_class_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
39
+ 'unsigned' => true,
40
+ 'nullable' => true,
41
+ ), 'Product Class ID')
42
+ ->addColumn('tax_rate', Varien_Db_Ddl_Table::TYPE_DECIMAL, '12,4', array(
43
+ 'nullable' => true,
44
+ ), 'Tax Rate')
45
+ ->addColumn('created_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
46
+ 'default' => Varien_Db_Ddl_Table::TIMESTAMP_INIT,
47
+ ), 'Created At')
48
+ ->addColumn('updated_at', Varien_Db_Ddl_Table::TYPE_TIMESTAMP, null, array(
49
+ 'nullable' => true,
50
+ ), 'Updated At')
51
+ ->addIndex(
52
+ $installer->getIdxName('speedtax/failsafe_calculation_rate', array('country_id')),
53
+ array('country_id'),
54
+ array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX)
55
+ )
56
+ ->addIndex(
57
+ $installer->getIdxName('speedtax/failsafe_calculation_rate', array('region_id')),
58
+ array('region_id'),
59
+ array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX)
60
+ )
61
+ ->addIndex(
62
+ $installer->getIdxName('speedtax/failsafe_calculation_rate', array('postcode')),
63
+ array('postcode'),
64
+ array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX)
65
+ )
66
+ ->addIndex(
67
+ $installer->getIdxName('speedtax/failsafe_calculation_rate', array('customer_class_id')),
68
+ array('customer_class_id'),
69
+ array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX)
70
+ )
71
+ ->addIndex(
72
+ $installer->getIdxName('speedtax/failsafe_calculation_rate', array('product_class_id')),
73
+ array('product_class_id'),
74
+ array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_INDEX)
75
+ )
76
+ ->setComment('SpeedTax Failsafe Calculation Rate');
77
+ $installer->getConnection()->createTable( $calculationTable );
78
+
79
+ $installer->getConnection()->addColumn(
80
+ $installer->getTable('sales/order'),
81
+ "is_speedtax_failsafe_calculation",
82
+ "SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Is SpeedTax Failsafe Calculation'"
83
+ );
84
+
85
+ $installer->getConnection()->addColumn(
86
+ $installer->getTable('sales/invoice'),
87
+ "is_speedtax_failsafe_calculation",
88
+ "SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Is SpeedTax Failsafe Calculation'"
89
+ );
90
+ $installer->getConnection()->addColumn(
91
+ $installer->getTable('sales/invoice'),
92
+ "base_speedtax_tax_amount",
93
+ "DECIMAL(12,4) DEFAULT NULL COMMENT 'Base SpeedTax Tax Amount'"
94
+ );
95
+ $installer->getConnection()->addColumn(
96
+ $installer->getTable('sales/invoice'),
97
+ "speedtax_tax_amount",
98
+ "DECIMAL(12,4) DEFAULT NULL COMMENT 'SpeedTax Tax Amount'"
99
+ );
100
+
101
+ $installer->endSetup();
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>SalesTax_Connector</name>
4
- <version>3.1.8</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.harapartners.com/terms/eula">Hara Partners End User License Agreement</license>
7
  <channel>community</channel>
@@ -10,9 +10,9 @@
10
  <description>Simplify sales and use tax calculation, compliance, and management in the cloud! </description>
11
  <notes>Simplify sales and use tax calculation, compliance, and management in the cloud! </notes>
12
  <authors><author><name>Ken Nunes</name><user>kennuneswo</user><email>ken.nunes@wolterskluwer.com</email></author></authors>
13
- <date>2014-02-18</date>
14
- <time>00:45:48</time>
15
- <contents><target name="magecommunity"><dir name="Harapartners"><dir name="SpeedTax"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Authentication.php" hash="8be5a91c0aa3d23ced5a2852b940dac3"/></dir></dir></dir></dir></dir></dir><dir name="Helper"><dir name="Connector"><file name="Data.php" hash="4ae2eb94b6cf797eef7e2a7a8249e073"/><file name="Speedtax.php" hash="b81e16f25f4f51a6544c44301ec00667"/></dir><file name="Data.php" hash="4a3805bc334300c5b79afa89a3330be6"/><file name="Processor.php" hash="600241518208610cc76ffd6051d1cb6a"/></dir><dir name="Model"><file name="Observer.php" hash="609d1237bc2eddedeb629ed322540fc8"/><dir name="Rewrite"><dir name="Tax"><dir name="Sales"><dir name="Total"><dir name="Quote"><file name="Tax.php" hash="00a4b49781a30b5b19ea82b083dcd2df"/></dir></dir></dir></dir></dir><file name="Session.php" hash="46175fe01434d91757499d5c0f7f2bee"/><dir name="Source"><file name="Usregions.php" hash="2ab7713b5b46f142e133459952cd1ef5"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><dir name="System"><dir name="Config"><file name="AjaxController.php" hash="fbb6a35c7f2c0706f39160413ced8b2f"/></dir></dir></dir></dir><dir name="etc"><file name="config.xml" hash="5021e1fc50747a23d68b9d0e00721e85"/><file name="system.xml" hash="945c43e0653cbdb934578cae6039a830"/></dir><dir name="sql"><dir name="speedtax_setup"><file name="mysql4-upgrade-3.0.9-3.1.0.php" hash="886b0ebdd5b0234b89fcff5fc07fbfd1"/></dir></dir></dir><dir name="ConnectorHub"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Json.php" hash="9dfc33f951be4c545c757e7d9724eb8c"/></dir></dir></dir></dir></dir></dir><dir name="Helper"><dir name="Connector"><file name="Config.php" hash="ded948bc18c602d6fc9c148cd826245a"/><file name="Core.php" hash="503eddf9049c7f7fc0b0494a51d21b5d"/></dir><file name="Mcrypt.php" hash="928572b4884d60f03ecde04b63186ea2"/><file name="Object.php" hash="487cd77c21c8bb9dec6189cc19d8c6a5"/></dir><dir name="Model"><file name="Observer.php" hash="d6d7f852fbde7e14e6fdd5f7c75e77cd"/><dir name="Rewrite"><dir name="Paypal"><dir name="Api"><file name="Nvp.php" hash="e260f23f4093e7932286f81bf48f855a"/></dir><file name="Config.php" hash="41db0559b01ef40fa3a33e85a416d016"/></dir></dir></dir><dir name="etc"><file name="config.xml" hash="4e0fc6a2496f4f7b871b8e389ff11b39"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Harapartners_SpeedTax.xml" hash="fc395d2c5a12e41f920f032c1541bd08"/><file name="Harapartners_ConnectorHub.xml" hash="f553017467b4b32a76b1af8d32765049"/></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>SalesTax_Connector</name>
4
+ <version>3.2.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.harapartners.com/terms/eula">Hara Partners End User License Agreement</license>
7
  <channel>community</channel>
10
  <description>Simplify sales and use tax calculation, compliance, and management in the cloud! </description>
11
  <notes>Simplify sales and use tax calculation, compliance, and management in the cloud! </notes>
12
  <authors><author><name>Ken Nunes</name><user>kennuneswo</user><email>ken.nunes@wolterskluwer.com</email></author></authors>
13
+ <date>2014-07-25</date>
14
+ <time>21:46:36</time>
15
+ <contents><target name="magecommunity"><dir name="Harapartners"><dir name="SpeedTax"><dir name="Block"><dir name="Adminhtml"><dir name="Invoice"><dir name="All"><dir name="Index"><file name="Grid.php" hash="9e30ba4540d93b90931653a26be84ca5"/></dir><file name="Index.php" hash="3bd888b08743237ba8cd5a3366b82487"/></dir><dir name="Failsafe"><dir name="Index"><file name="Grid.php" hash="8f8e68705a3f7abab5e93d114df741ca"/></dir><file name="Index.php" hash="a96810237abda83a9a6d6f7397a4847d"/></dir><dir name="Rateverification"><dir name="Index"><file name="Grid.php" hash="890971679f6eb41955ff0bd5ed7dac70"/></dir><file name="Index.php" hash="1c4345559aa6ed8e648e5ffd3d57f4bb"/></dir></dir><file name="Notification.php" hash="3b0541ce8d61c567ef5431c23f078e13"/><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Authentication.php" hash="8be5a91c0aa3d23ced5a2852b940dac3"/></dir></dir></dir></dir></dir></dir><dir name="Helper"><dir name="Connector"><file name="Data.php" hash="ec2d5c31c759d72834c4d1664b29de2f"/><file name="Speedtax.php" hash="5ab1b418b258cc574eef0542490a096e"/></dir><file name="Data.php" hash="b5f093dcc4a15f65ac0ba4decbf1f21b"/><file name="Failsafe.php" hash="f41b5e97350fe47b1b6fa73653b49871"/><file name="Processor.php" hash="1db8a77649751e8002d7779d80a145f3"/></dir><dir name="Model"><dir name="Failsafe"><dir name="Calculation"><file name="Rate.php" hash="811902f52d9fe42c71f5834b5f78fba9"/></dir><file name="Calculation.php" hash="892f32e0082bff2700ac7a8d98fe4a5a"/><dir name="Sales"><dir name="Total"><dir name="Quote"><file name="Tax.php" hash="c367a1e87a3d59299ad2d4ef6d3b8865"/></dir></dir></dir></dir><file name="Observer.php" hash="2319c1c9d941ef00935cb71b52921030"/><dir name="Resource"><dir name="Failsafe"><dir name="Calculation"><dir name="Rate"><file name="Collection.php" hash="2a1c5730b4be51104a27009300eb13c1"/></dir><file name="Rate.php" hash="59a6d553ad7544d431b7952aeeb6b8e7"/></dir></dir></dir><dir name="Rewrite"><dir name="Tax"><dir name="Sales"><dir name="Total"><dir name="Quote"><file name="Tax.php" hash="266bcbb46c333e594869ce3fb51b9a49"/></dir></dir></dir></dir></dir><file name="Session.php" hash="46175fe01434d91757499d5c0f7f2bee"/><dir name="Source"><file name="Usregions.php" hash="2ab7713b5b46f142e133459952cd1ef5"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="InvoiceController.php" hash="ad4c95583b2f36a2b9b3715cdb96440e"/><file name="NotificationController.php" hash="1221b23c9a8612fb9913a40c7fd639a8"/><dir name="System"><dir name="Config"><file name="AjaxController.php" hash="83fad83760a495f4915d4d369c4550b1"/></dir></dir></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="9489898787655e78c390e036b4897aa5"/><file name="config.xml" hash="2f31e4d26f232a2c94d7677beacbffcb"/><file name="system.xml" hash="a9e26cb879487f522a18d2b7b4e212a7"/></dir><dir name="sql"><dir name="speedtax_setup"><file name="mysql4-upgrade-3.0.9-3.1.0.php" hash="c3f6ae6b94d838d019c1ffa86f4fb2cc"/><file name="mysql4-upgrade-3.9.9-4.0.0.php" hash="8603060cf362ca9303c3e28c5c00c0da"/></dir></dir></dir><dir name="ConnectorHub"><dir name="Block"><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Json.php" hash="f6df5fa48d5e7daa0f5d646fe8572402"/></dir></dir></dir></dir></dir></dir><dir name="Helper"><dir name="Connector"><file name="Config.php" hash="7602770c8362d6edad15e2ed9d0419d1"/><file name="Core.php" hash="edcc593b8e8fd8d079182adc1bca99b8"/></dir><file name="Mcrypt.php" hash="928572b4884d60f03ecde04b63186ea2"/><file name="Object.php" hash="487cd77c21c8bb9dec6189cc19d8c6a5"/></dir><dir name="Model"><file name="Observer.php" hash="d6d7f852fbde7e14e6fdd5f7c75e77cd"/><dir name="Rewrite"><dir name="Paypal"><dir name="Api"><file name="Nvp.php" hash="e260f23f4093e7932286f81bf48f855a"/></dir><file name="Config.php" hash="642ee9fdd6ec30b8b18f9becab5b0682"/></dir></dir></dir><dir name="etc"><file name="config.xml" hash="4e0fc6a2496f4f7b871b8e389ff11b39"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Harapartners_SpeedTax.xml" hash="fc395d2c5a12e41f920f032c1541bd08"/><file name="Harapartners_ConnectorHub.xml" hash="f553017467b4b32a76b1af8d32765049"/></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php></required></dependencies>
18
  </package>