Version Notes
Supported Magento 1.5.0.0 - 1.7.x, Magento Enterprise 1.8-1.12.x
Download this release
Release Info
Developer | Exactor, Inc. |
Extension | Mage_Exactor_Tax |
Version | 2012.09.20 |
Comparing to | |
See all releases |
Code changes from version 2012.07.23 to 2012.09.20
- app/code/local/Exactor/Core/Helper/SessionCache.php +4 -0
- app/code/local/Exactor/ExactorSettings/controllers/Adminhtml/FormController.php +1 -0
- app/code/local/Exactor/Sales/Model/Observer.php +77 -24
- app/code/local/Exactor/Sales/etc/config.xml +10 -3
- app/code/local/Exactor/Tax/Helper/Mapping.php +219 -37
- app/code/local/Exactor/Tax/Model/Sales/Total/Quote/Tax.php +15 -2
- app/code/local/Exactor/Tax/etc/config.xml +1 -1
- app/design/adminhtml/default/default/template/ExactorSettings/settingsform.phtml +27 -17
- lib/ExactorCommons/ExactorCommons.php +41 -0
- lib/ExactorCommons/ExactorDomainObjects.php +1 -1
- lib/ExactorCommons/RegionResolver.php +175 -0
- lib/ExactorCommons/config.php +1 -1
- package.xml +5 -5
app/code/local/Exactor/Core/Helper/SessionCache.php
CHANGED
@@ -37,6 +37,9 @@ class Exactor_Core_Helper_SessionCache extends Mage_Core_Helper_Abstract{
|
|
37 |
return null;
|
38 |
}
|
39 |
|
|
|
|
|
|
|
40 |
public function popTransactionInfo(){
|
41 |
$transactionsArray = $this->fetchAll();
|
42 |
if (count($transactionsArray) == 0) return;
|
@@ -51,6 +54,7 @@ class Exactor_Core_Helper_SessionCache extends Mage_Core_Helper_Abstract{
|
|
51 |
*/
|
52 |
public function clear(){
|
53 |
$this->magentoSession->setExactorTransactionInfo(null);
|
|
|
54 |
}
|
55 |
|
56 |
/**
|
37 |
return null;
|
38 |
}
|
39 |
|
40 |
+
/**
|
41 |
+
* @return ExactorTransactionInfo
|
42 |
+
*/
|
43 |
public function popTransactionInfo(){
|
44 |
$transactionsArray = $this->fetchAll();
|
45 |
if (count($transactionsArray) == 0) return;
|
54 |
*/
|
55 |
public function clear(){
|
56 |
$this->magentoSession->setExactorTransactionInfo(null);
|
57 |
+
$this->magentoSession->setExactorTransactionInfoArray(null);
|
58 |
}
|
59 |
|
60 |
/**
|
app/code/local/Exactor/ExactorSettings/controllers/Adminhtml/FormController.php
CHANGED
@@ -54,6 +54,7 @@ class Exactor_ExactorSettings_Adminhtml_FormController extends Mage_Adminhtml_Co
|
|
54 |
require_once($libDir . '/XmlProcessing.php');
|
55 |
require_once($libDir . '/ExactorDomainObjects.php');
|
56 |
require_once($libDir . '/ExactorCommons.php');
|
|
|
57 |
// Magento specific definitions
|
58 |
require_once($libDir . '/Magento.php');
|
59 |
require_once($libDir . '/config.php');
|
54 |
require_once($libDir . '/XmlProcessing.php');
|
55 |
require_once($libDir . '/ExactorDomainObjects.php');
|
56 |
require_once($libDir . '/ExactorCommons.php');
|
57 |
+
require_once($libDir . '/RegionResolver.php');
|
58 |
// Magento specific definitions
|
59 |
require_once($libDir . '/Magento.php');
|
60 |
require_once($libDir . '/config.php');
|
app/code/local/Exactor/Sales/Model/Observer.php
CHANGED
@@ -11,10 +11,13 @@ class Exactor_Sales_Model_Observer {
|
|
11 |
private $exactorSettingsHelper;
|
12 |
/** @var Exactor_Core_Helper_SessionCache */
|
13 |
private $sessionCache;
|
14 |
-
/** @var Exactor_Core_Model_MerchantSettings */
|
15 |
-
private $merchantSettings;
|
16 |
/** @var ExactorProcessingService*/
|
17 |
private $exactorProcessingService;
|
|
|
|
|
|
|
|
|
|
|
18 |
/** @var IExactorLogger */
|
19 |
private $logger;
|
20 |
|
@@ -23,6 +26,7 @@ class Exactor_Sales_Model_Observer {
|
|
23 |
require_once($libDir . '/XmlProcessing.php');
|
24 |
require_once($libDir . '/ExactorDomainObjects.php');
|
25 |
require_once($libDir . '/ExactorCommons.php');
|
|
|
26 |
// Magento specific definitions
|
27 |
require_once($libDir . '/Magento.php');
|
28 |
require_once($libDir . '/config.php');
|
@@ -34,6 +38,7 @@ class Exactor_Sales_Model_Observer {
|
|
34 |
$this->logger = ExactorLoggingFactory::getInstance()->getLogger($this);
|
35 |
$this->exactorSettingsHelper = Mage::helper('ExactorSettings');
|
36 |
$this->sessionCache = Mage::helper('Exactor_Core_SessionCache/');
|
|
|
37 |
}
|
38 |
|
39 |
/**
|
@@ -73,34 +78,65 @@ class Exactor_Sales_Model_Observer {
|
|
73 |
}
|
74 |
}
|
75 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
public function handleAllOrdersCompleted(Varien_Event_Observer $observer){
|
|
|
77 |
if (is_array($observer->getOrders()))
|
78 |
$orders = array_reverse($observer->getOrders());
|
79 |
else
|
80 |
$orders = array($observer->getOrder());
|
81 |
foreach($orders as $order){
|
82 |
-
$
|
83 |
-
if ($merchantSettings==null) continue;
|
84 |
-
$transactionInfo = $this->sessionCache->popTransactionInfo($order);
|
85 |
-
if ($transactionInfo == null){
|
86 |
-
$this->logger->error('Nothing to process. There is no transaction in the session cache', 'handleCreatedOrder');
|
87 |
-
return;
|
88 |
-
}
|
89 |
-
// Update transaction info with order information
|
90 |
-
$orderId = $order->getIncrementId();
|
91 |
-
$transactionInfo->setShoppingCartTrnId($orderId);
|
92 |
-
// Push latest transaction from the Session to DB
|
93 |
-
$this->exactorProcessingService->getPluginCallback()->saveTransactionInfo($transactionInfo,$transactionInfo->getSignature());
|
94 |
-
// if CommitOption is set up to commit on sales order - do commit the
|
95 |
-
// latest transaction from the session storage
|
96 |
-
if ($merchantSettings->getCommitOption() == Exactor_Core_Model_MerchantSettings::COMMIT_ON_SALES_ORDER){
|
97 |
-
$this->exactorProcessingService->commitExistingInvoiceForOrder($orderId);
|
98 |
-
}
|
99 |
}
|
100 |
// We need to clean the session storage here
|
101 |
$this->sessionCache->clear();
|
102 |
}
|
103 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
/**
|
105 |
* Event will be fired once new order has been created
|
106 |
* @param Varien_Event_Observer $observer
|
@@ -108,22 +144,39 @@ class Exactor_Sales_Model_Observer {
|
|
108 |
*/
|
109 |
public function handleCreatedOrder(Varien_Event_Observer $observer){
|
110 |
$this->logger->trace('called', 'handleCreatedOrder');
|
111 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
}
|
113 |
|
114 |
public function handleNewCreditMemo(Varien_Event_Observer $observer){
|
115 |
$this->logger->trace('called', 'handleNewCreditMemo');
|
116 |
$merchantSettings = $this->loadMerchantSettings($observer->getCreditmemo()->getOrder());
|
117 |
if ($merchantSettings==null) return;
|
118 |
-
$
|
119 |
-
$this->refundTransactionForOrder($orderId);
|
120 |
}
|
121 |
|
122 |
public function handleCancelOrder(Varien_Event_Observer $observer){
|
123 |
$this->logger->trace('called', 'handleCancelOrder');
|
124 |
-
$merchantSettings = $this->loadMerchantSettings($observer->getOrder());
|
125 |
if ($merchantSettings==null) return;
|
126 |
-
$orderId = $observer->getOrder()->getIncrementId();
|
127 |
$this->refundTransactionForOrder($orderId);
|
128 |
}
|
129 |
|
11 |
private $exactorSettingsHelper;
|
12 |
/** @var Exactor_Core_Helper_SessionCache */
|
13 |
private $sessionCache;
|
|
|
|
|
14 |
/** @var ExactorProcessingService*/
|
15 |
private $exactorProcessingService;
|
16 |
+
/**
|
17 |
+
* @var Exactor_Tax_Helper_Mapping
|
18 |
+
*/
|
19 |
+
private $exactorMappingHelper;
|
20 |
+
|
21 |
/** @var IExactorLogger */
|
22 |
private $logger;
|
23 |
|
26 |
require_once($libDir . '/XmlProcessing.php');
|
27 |
require_once($libDir . '/ExactorDomainObjects.php');
|
28 |
require_once($libDir . '/ExactorCommons.php');
|
29 |
+
require_once($libDir . '/RegionResolver.php');
|
30 |
// Magento specific definitions
|
31 |
require_once($libDir . '/Magento.php');
|
32 |
require_once($libDir . '/config.php');
|
38 |
$this->logger = ExactorLoggingFactory::getInstance()->getLogger($this);
|
39 |
$this->exactorSettingsHelper = Mage::helper('ExactorSettings');
|
40 |
$this->sessionCache = Mage::helper('Exactor_Core_SessionCache/');
|
41 |
+
$this->exactorMappingHelper = Mage::helper('tax/mapping');
|
42 |
}
|
43 |
|
44 |
/**
|
78 |
}
|
79 |
}
|
80 |
|
81 |
+
/**
|
82 |
+
* Stores order in our local DB, Commits transaction if needed.
|
83 |
+
* Returns false if for some reason operation wasn't successful.
|
84 |
+
*
|
85 |
+
* @param $order
|
86 |
+
* @return bool
|
87 |
+
*/
|
88 |
+
private function processFinishedOrder($order){
|
89 |
+
$merchantSettings = $this->loadMerchantSettings($order);
|
90 |
+
if ($merchantSettings==null) false;
|
91 |
+
$transactionInfo = $this->sessionCache->popTransactionInfo($order);
|
92 |
+
if ($transactionInfo == null){
|
93 |
+
$this->logger->error('Nothing to process. There is no transaction in the session cache', 'handleAllOrdersCompleted');
|
94 |
+
return false;
|
95 |
+
}
|
96 |
+
// Update transaction info with order information
|
97 |
+
$orderId = $order->getIncrementId();
|
98 |
+
$transactionInfo->setShoppingCartTrnId($orderId);
|
99 |
+
// Push latest transaction from the Session to DB
|
100 |
+
$this->exactorProcessingService->getPluginCallback()->saveTransactionInfo($transactionInfo,$transactionInfo->getSignature());
|
101 |
+
// if CommitOption is set up to commit on sales order - do commit the
|
102 |
+
// latest transaction from the session storage
|
103 |
+
if ($merchantSettings->getCommitOption() == Exactor_Core_Model_MerchantSettings::COMMIT_ON_SALES_ORDER){
|
104 |
+
$this->logger->info("Commiting transaction for order $orderId - " . $transactionInfo->getExactorTrnId(), 'handleAllOrdersCompleted');
|
105 |
+
$this->exactorProcessingService->commitExistingInvoiceForOrder($orderId);
|
106 |
+
}
|
107 |
+
return true;
|
108 |
+
}
|
109 |
+
|
110 |
public function handleAllOrdersCompleted(Varien_Event_Observer $observer){
|
111 |
+
$this->logger->trace('called', 'handleAllOrdersCompleted');
|
112 |
if (is_array($observer->getOrders()))
|
113 |
$orders = array_reverse($observer->getOrders());
|
114 |
else
|
115 |
$orders = array($observer->getOrder());
|
116 |
foreach($orders as $order){
|
117 |
+
$this->processFinishedOrder($order);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
}
|
119 |
// We need to clean the session storage here
|
120 |
$this->sessionCache->clear();
|
121 |
}
|
122 |
|
123 |
+
private function partialRefund(Mage_Sales_Model_Order_Creditmemo $creditMemo){
|
124 |
+
$transactionInfo = $this->exactorProcessingService->loadTransactionInfoByOrderId($creditMemo->getOrder()->getIncrementId());
|
125 |
+
if ($transactionInfo==null || !$transactionInfo->getIsCommited()){
|
126 |
+
$this->logger->info("Exactor transaction for order " .
|
127 |
+
$creditMemo->getOrder()->getIncrementId() . "doesn't exists or wasn't commited", 'partialRefund' );
|
128 |
+
return;
|
129 |
+
}
|
130 |
+
$merchantSettings = $this->loadMerchantSettings($creditMemo->getOrder());
|
131 |
+
if ($merchantSettings==null) return;
|
132 |
+
$invoiceRequests = $this->exactorMappingHelper->buildInvoiceRequestsForCreditMemo($creditMemo, $merchantSettings);
|
133 |
+
$exactorProcessingService = ExactorProcessingServiceFactory::getInstance()->buildExactorProcessingService($merchantSettings->getMerchantID(),
|
134 |
+
$merchantSettings->getUserID());
|
135 |
+
foreach ($invoiceRequests as $invoice) {
|
136 |
+
$exactorProcessingService->partialRefund($invoice, new DateTime(), $creditMemo->getOrder()->getIncrementId());
|
137 |
+
}
|
138 |
+
}
|
139 |
+
|
140 |
/**
|
141 |
* Event will be fired once new order has been created
|
142 |
* @param Varien_Event_Observer $observer
|
144 |
*/
|
145 |
public function handleCreatedOrder(Varien_Event_Observer $observer){
|
146 |
$this->logger->trace('called', 'handleCreatedOrder');
|
147 |
+
if ($this->shouldOrderProcessingRunInCompatibilityMode($observer->getOrder())) {
|
148 |
+
$this->logger->info('Order processing started in compatibility mode.', 'handleCreatedOrder');
|
149 |
+
$this->processFinishedOrder($observer->getOrder());
|
150 |
+
$this->sessionCache->clear();
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
private function shouldOrderProcessingRunInCompatibilityMode($order) {
|
155 |
+
if ($order->getPayment() != null &&
|
156 |
+
strpos($order->getPayment()->getMethod(), "paypal_express") !== false){
|
157 |
+
$this->logger->info('PayPal order detected', 'shouldOrderProcessingRunInCompatibilityMode');
|
158 |
+
return true;
|
159 |
+
}
|
160 |
+
$mageVersionInfo = Mage::getVersionInfo();
|
161 |
+
if ($mageVersionInfo['major']==1 && $mageVersionInfo['minor'] == 8){
|
162 |
+
$this->logger->info('Magento Enterprise detected', 'shouldOrderProcessingRunInCompatibilityMode');
|
163 |
+
return true;
|
164 |
+
}
|
165 |
+
return false;
|
166 |
}
|
167 |
|
168 |
public function handleNewCreditMemo(Varien_Event_Observer $observer){
|
169 |
$this->logger->trace('called', 'handleNewCreditMemo');
|
170 |
$merchantSettings = $this->loadMerchantSettings($observer->getCreditmemo()->getOrder());
|
171 |
if ($merchantSettings==null) return;
|
172 |
+
$this->partialRefund($observer->getCreditmemo());
|
|
|
173 |
}
|
174 |
|
175 |
public function handleCancelOrder(Varien_Event_Observer $observer){
|
176 |
$this->logger->trace('called', 'handleCancelOrder');
|
177 |
+
$merchantSettings = $this->loadMerchantSettings($observer->getPayment()->getOrder());
|
178 |
if ($merchantSettings==null) return;
|
179 |
+
$orderId = $observer->getPayment()->getOrder()->getIncrementId();
|
180 |
$this->refundTransactionForOrder($orderId);
|
181 |
}
|
182 |
|
app/code/local/Exactor/Sales/etc/config.xml
CHANGED
@@ -28,7 +28,7 @@
|
|
28 |
<config>
|
29 |
<modules>
|
30 |
<Exactor_Sales>
|
31 |
-
<version>2012.
|
32 |
</Exactor_Sales>
|
33 |
</modules>
|
34 |
<global>
|
@@ -60,7 +60,7 @@
|
|
60 |
</exactor_sales_observer>
|
61 |
</observers>
|
62 |
</sales_order_creditmemo_refund>
|
63 |
-
<
|
64 |
<observers>
|
65 |
<exactor_sales_observer>
|
66 |
<type>singleton</type>
|
@@ -68,7 +68,7 @@
|
|
68 |
<method>handleCancelOrder</method>
|
69 |
</exactor_sales_observer>
|
70 |
</observers>
|
71 |
-
</
|
72 |
<sales_order_shipment_save_after>
|
73 |
<observers>
|
74 |
<exactor_sales_observer>
|
@@ -88,5 +88,12 @@
|
|
88 |
</observers>
|
89 |
</sales_order_invoice_pay>
|
90 |
</events>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
</global>
|
92 |
</config>
|
28 |
<config>
|
29 |
<modules>
|
30 |
<Exactor_Sales>
|
31 |
+
<version>2012.08.28</version>
|
32 |
</Exactor_Sales>
|
33 |
</modules>
|
34 |
<global>
|
60 |
</exactor_sales_observer>
|
61 |
</observers>
|
62 |
</sales_order_creditmemo_refund>
|
63 |
+
<sales_order_payment_cancel>
|
64 |
<observers>
|
65 |
<exactor_sales_observer>
|
66 |
<type>singleton</type>
|
68 |
<method>handleCancelOrder</method>
|
69 |
</exactor_sales_observer>
|
70 |
</observers>
|
71 |
+
</sales_order_payment_cancel>
|
72 |
<sales_order_shipment_save_after>
|
73 |
<observers>
|
74 |
<exactor_sales_observer>
|
88 |
</observers>
|
89 |
</sales_order_invoice_pay>
|
90 |
</events>
|
91 |
+
<models>
|
92 |
+
<tax>
|
93 |
+
<rewrite>
|
94 |
+
<sales_model_order_creditmemo_total_tax>Exactor_Sales_Model_Order_Creditmemo_Total_Tax</sales_model_order_creditmemo_total_tax>
|
95 |
+
</rewrite>
|
96 |
+
</tax>
|
97 |
+
</models>
|
98 |
</global>
|
99 |
</config>
|
app/code/local/Exactor/Tax/Helper/Mapping.php
CHANGED
@@ -11,15 +11,21 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
11 |
const EUC_SHIPPING_USPS='EUC-13030202';
|
12 |
const EUC_SHIPPING_AND_HANDLING='EUC-13010101';
|
13 |
const EUC_HANDLING = 'EUC-13010301';
|
|
|
|
|
14 |
|
15 |
const MSG_DEFAULT_SHIPPING_NAME = 'Default Shipping';
|
16 |
const MSG_HANDLING_FEE = 'Handling Fee';
|
|
|
17 |
const MSG_SHIPPING_DESCRIPTION_PREFIX = 'Shipping Fee: ';
|
18 |
const MSG_ESTIMATION_REQUEST = 'Magento Tax Estimation Request';
|
19 |
const MSG_DISCOUNTED_BY = 'Discounted by $';
|
|
|
|
|
20 |
|
21 |
const LINE_ITEM_ID_SHIPPING = "SHIPPING";
|
22 |
const LINE_ITEM_ID_HANDLING = "HANDLING";
|
|
|
23 |
const INDEXED_LINE_ITEM_ID_PREFIX = '_';
|
24 |
|
25 |
const ATTRIBUTE_NAME_EXEMPTION = 'taxvat';
|
@@ -32,8 +38,11 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
32 |
const PO_ESTIMATE_TEXT = 'Estimated Tax ';
|
33 |
|
34 |
const UNKNOWN_STREET_TEXT = "";
|
|
|
|
|
35 |
|
36 |
|
|
|
37 |
|
38 |
private function getLogger(){
|
39 |
if ($this->logger==null)
|
@@ -57,7 +66,7 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
57 |
return join(' ', $parts);
|
58 |
}
|
59 |
|
60 |
-
|
61 |
$exactorAddress = new AddressType();
|
62 |
if ($address==null) return null;
|
63 |
// Set defaults
|
@@ -65,7 +74,7 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
65 |
$exactorAddress->setFullName("Unknown Buyer");
|
66 |
//
|
67 |
$fullName = trim($address->getName());//trim($this->buildFullName($address->getFirstname(), $address->getLastname(), $address->getMiddlename()));
|
68 |
-
if (strlen($fullName)>
|
69 |
$exactorAddress->setFullName($fullName);
|
70 |
if ($address->getStreetFull() != null)
|
71 |
$exactorAddress->setStreet1($address->getStreetFull());
|
@@ -76,27 +85,45 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
76 |
return $exactorAddress;
|
77 |
}
|
78 |
|
79 |
-
public function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
81 |
$sku='';
|
|
|
|
|
|
|
|
|
|
|
82 |
switch ($merchantSettings->getSourceOfSKU()){
|
83 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_NONE:
|
84 |
$sku = '';
|
85 |
break;
|
86 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_SKU_FIELD:
|
87 |
-
$sku = $magentoItem->getSku()
|
88 |
break;
|
89 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_ATTRIBUTE_NAME:
|
90 |
$attributeSetName = 'Default';
|
91 |
try{
|
92 |
$attributeSetModel = Mage::getModel("eav/entity_attribute_set");
|
93 |
-
$attributeSetModel->load($
|
94 |
$attributeSetName = $attributeSetModel->getAttributeSetName();
|
95 |
}catch(Exception $e){}
|
96 |
$sku = $attributeSetName;
|
97 |
break;
|
98 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_PRODUCT_CATEGORY:
|
99 |
-
$category = $
|
100 |
if ($category != null)
|
101 |
$sku = $category->getName();
|
102 |
break;
|
@@ -104,11 +131,11 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
104 |
/** @var Mage_Tax_Model_Mysql4_Class_Collection $taxClassCollection */
|
105 |
$taxClassCollection = Mage::getModel('tax/class')->getCollection();
|
106 |
/** @var Mage_Tax_Model_Class $taxClass */
|
107 |
-
$taxClass = $taxClassCollection->getItemById($
|
108 |
if ($taxClass == null) $sku = ''; else $sku = $taxClass->getClassName();
|
109 |
break;
|
110 |
}
|
111 |
-
return substr($sku,
|
112 |
}
|
113 |
|
114 |
private function isUSPSShipping($methodName){
|
@@ -121,20 +148,40 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
121 |
return false;
|
122 |
}
|
123 |
|
124 |
-
public function
|
125 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
|
|
126 |
if ($quoteAddress->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_BILLING) return null; // There is no shipping fees there
|
127 |
-
if ($quoteAddress->getShippingAmount()==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
128 |
$shippingLineItem = new LineItemType();
|
129 |
-
$shippingLineItem->setDescription(self::MSG_SHIPPING_DESCRIPTION_PREFIX . $
|
130 |
if (trim($shippingLineItem->getDescription())==''){
|
131 |
$shippingLineItem->setDescription(self::MSG_DEFAULT_SHIPPING_NAME);
|
132 |
-
}
|
133 |
// Get EUC code for shipping
|
134 |
$shippingEUC = self::EUC_SHIPPING_COMMON_CARRIER;
|
135 |
if ($merchantSettings->isShippingIncludeHandling()){
|
136 |
$shippingEUC = self::EUC_SHIPPING_AND_HANDLING;
|
137 |
-
}else if ($this->isUSPSShipping($
|
138 |
$shippingEUC = self::EUC_SHIPPING_USPS;
|
139 |
}
|
140 |
$shippingLineItem->setSKU($shippingEUC);
|
@@ -142,55 +189,61 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
142 |
$shippingLineItem->setId(self::LINE_ITEM_ID_SHIPPING);
|
143 |
$shippingLineItem->setQuantity(1);
|
144 |
// If shipping doesn't include handling we should subtract handling from the total shipping amount
|
145 |
-
$amount = $quoteAddress->getShippingAmount();
|
146 |
if (!$merchantSettings->isShippingIncludeHandling()){
|
147 |
-
$amount -= $this->getHandlingFeeByMethodName($
|
148 |
}
|
149 |
$shippingLineItem->setGrossAmount($amount);
|
150 |
-
$this->applyDiscountToLineItem($shippingLineItem,$
|
151 |
return $shippingLineItem;
|
152 |
}
|
153 |
|
|
|
|
|
154 |
/**
|
155 |
* Returns handling feed amount by given name, or 0 if there is no handling
|
156 |
* @param $name
|
157 |
* @return void
|
158 |
*/
|
159 |
private function getHandlingFeeByMethodName($name){
|
160 |
-
if (strpos($name, "_")) $name = substr($name,
|
|
|
161 |
// Fetch carriers information from Magento config to determine handling amount
|
162 |
$carriers = Mage::getStoreConfig('carriers');
|
163 |
-
if (!array_key_exists($name, $carriers)) return
|
164 |
foreach($carriers as $id => $carrier){
|
165 |
-
if (array_key_exists('handling_fee', $carrier)
|
166 |
if ($id == $name)
|
167 |
return $carrier['handling_fee'];
|
168 |
}
|
169 |
}
|
170 |
-
return
|
171 |
}
|
172 |
|
173 |
-
public function getHandlingLineItem(
|
174 |
-
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
175 |
-
if ($quoteAddress->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_BILLING) return null; // There is no shipping fees there
|
176 |
if ($merchantSettings->isShippingIncludeHandling()) return null; // Handling already included in the shipping
|
177 |
$handlingLineItem = new LineItemType();
|
178 |
$handlingLineItem->setId(self::LINE_ITEM_ID_HANDLING);
|
179 |
$handlingLineItem->setDescription(self::MSG_HANDLING_FEE);
|
180 |
$handlingLineItem->setSKU(self::EUC_HANDLING);
|
181 |
$handlingLineItem->setQuantity(1);
|
182 |
-
$handlingLineItem->setGrossAmount($this->getHandlingFeeByMethodName($
|
183 |
-
if ($handlingLineItem->getGrossAmount()==
|
184 |
return $handlingLineItem;
|
185 |
}
|
186 |
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
/**
|
188 |
* @param \Mage_Sales_Model_Quote_Address_Item|\Mage_Sales_Model_Quote_Item $magentoItem
|
189 |
* @param Mage_Sales_Model_Quote_Address $quoteAddress
|
190 |
* @param Exactor_Core_Model_MerchantSettings $merchantSettings
|
191 |
* @return LineItemType
|
192 |
*/
|
193 |
-
public function buildLineItemForMagentoItem(
|
194 |
Mage_Sales_Model_Quote_Address $quoteAddress,
|
195 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
196 |
$lineItem = new LineItemType();
|
@@ -199,21 +252,35 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
199 |
$lineItem->setGrossAmount($magentoItem->getBaseRowTotal());
|
200 |
else
|
201 |
$lineItem->setGrossAmount(0.0);
|
|
|
|
|
202 |
$lineItem->setQuantity($magentoItem->getTotalQty());
|
203 |
-
|
|
|
|
|
|
|
|
|
204 |
$this->applyDiscountToLineItem($lineItem, $magentoItem->getDiscountAmount());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
205 |
return $lineItem;
|
206 |
}
|
207 |
|
208 |
public function applyDiscountToLineItem(LineItemType &$item, $discountAmount=0){
|
209 |
-
if ($discountAmount>
|
210 |
$discountedLine = self::MSG_DISCOUNTED_BY . $discountAmount;
|
211 |
$item->setDescription($item->getDescription() . " ($discountedLine)");
|
212 |
$item->setGrossAmount($item->getGrossAmount() - $discountAmount);
|
213 |
}
|
214 |
}
|
215 |
|
216 |
-
|
217 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
218 |
$exemptionId = '';
|
219 |
if ($merchantSettings->getExemptionsSupported()){
|
@@ -223,34 +290,65 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
223 |
return $exemptionId;
|
224 |
}
|
225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
private function getCurrentCurrencyCode(Mage_Sales_Model_Quote_Address $quoteAddress){
|
227 |
$store = Mage::app()->getStore();
|
228 |
if ($quoteAddress->getQuote() != null && $quoteAddress->getQuote()->getStoreId() != null){
|
229 |
$store = $quoteAddress->getQuote()->getStore();
|
230 |
}
|
231 |
-
|
232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
return $currency;
|
234 |
}
|
235 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
/**
|
237 |
* @param Mage_Sales_Model_Quote_Address $quoteAddress
|
238 |
* @param Exactor_Core_Model_MerchantSettings $merchantSettings
|
239 |
* @param bool $isMultishipping
|
|
|
240 |
* @return InvoiceRequestType
|
241 |
*/
|
242 |
public function buildInvoiceRequestForQuoteAddress(Mage_Sales_Model_Quote_Address $quoteAddress,
|
243 |
Exactor_Core_Model_MerchantSettings $merchantSettings,
|
244 |
-
$isMultishipping){
|
245 |
// Building Invoice Parts
|
246 |
$shipToAddress = $this->buildExactorAddressForQuoteAddress($quoteAddress);
|
247 |
// Trying to find billing address in the quote
|
248 |
$billingAddress = $this->buildExactorAddressForQuoteAddress($quoteAddress->getQuote()->getBillingAddress());
|
249 |
-
|
250 |
if ($isEstimation) $shipToAddress->setFullName(self::MSG_ESTIMATION_REQUEST);
|
251 |
// If this is just tax estimation for not logged in user
|
252 |
// we just need to use shipping as billing
|
253 |
if ($isEstimation){
|
|
|
|
|
|
|
|
|
|
|
254 |
$billingAddress = $shipToAddress;
|
255 |
}
|
256 |
// If shipping info unavailable - fallback to billing information
|
@@ -267,13 +365,14 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
267 |
$invoiceRequest->setExemptionId($this->getExemptionIdForQuoteAddress($quoteAddress, $merchantSettings));
|
268 |
// Line items list
|
269 |
$magentoItems = $quoteAddress->getAllItems();
|
270 |
-
$itemNum =
|
271 |
/**
|
272 |
* @var $magentoItem Mage_Sales_Model_Quote_Item
|
273 |
*/
|
274 |
foreach ($magentoItems as $magentoItem){
|
275 |
$exactorLineItem = $this->buildLineItemForMagentoItem($magentoItem, $quoteAddress, $merchantSettings);
|
276 |
-
$exactorLineItem
|
|
|
277 |
// If this is non-multishipping request we should set
|
278 |
// ship to address to billing address for VIRTUAL ITEMS
|
279 |
if (!$isMultishipping){
|
@@ -286,9 +385,92 @@ class Exactor_Tax_Helper_Mapping extends Mage_Core_Helper_Abstract {
|
|
286 |
}
|
287 |
$invoiceRequest->addLineItem($exactorLineItem);
|
288 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
// Shipping & Handling
|
290 |
-
$
|
291 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
return $invoiceRequest;
|
293 |
}
|
|
|
294 |
}
|
11 |
const EUC_SHIPPING_USPS='EUC-13030202';
|
12 |
const EUC_SHIPPING_AND_HANDLING='EUC-13010101';
|
13 |
const EUC_HANDLING = 'EUC-13010301';
|
14 |
+
const EUC_NON_TAXABLE = 'EUC-99990101';
|
15 |
+
const EUC_GIFT_CARD = self::EUC_NON_TAXABLE;
|
16 |
|
17 |
const MSG_DEFAULT_SHIPPING_NAME = 'Default Shipping';
|
18 |
const MSG_HANDLING_FEE = 'Handling Fee';
|
19 |
+
const MSG_ADJUSTMENTS = 'Adjustments';
|
20 |
const MSG_SHIPPING_DESCRIPTION_PREFIX = 'Shipping Fee: ';
|
21 |
const MSG_ESTIMATION_REQUEST = 'Magento Tax Estimation Request';
|
22 |
const MSG_DISCOUNTED_BY = 'Discounted by $';
|
23 |
+
const MSG_ADJUSTMENTS_REFUND = "Adjustments Refund";
|
24 |
+
const MSG_GIFT_CARD_ITEM = "Gift card(-s)";
|
25 |
|
26 |
const LINE_ITEM_ID_SHIPPING = "SHIPPING";
|
27 |
const LINE_ITEM_ID_HANDLING = "HANDLING";
|
28 |
+
const LINE_ITEM_ID_ADJUSTMENTS = "ADJUSTMENTS";
|
29 |
const INDEXED_LINE_ITEM_ID_PREFIX = '_';
|
30 |
|
31 |
const ATTRIBUTE_NAME_EXEMPTION = 'taxvat';
|
38 |
const PO_ESTIMATE_TEXT = 'Estimated Tax ';
|
39 |
|
40 |
const UNKNOWN_STREET_TEXT = "";
|
41 |
+
const UNKNOWN_STATE_NAME = "UNKNOWN";
|
42 |
+
const UNKNOWN_ZIP_CODE = "00000";
|
43 |
|
44 |
|
45 |
+
const PRICE_TYPE_DYNAMIC = 0;
|
46 |
|
47 |
private function getLogger(){
|
48 |
if ($this->logger==null)
|
66 |
return join(' ', $parts);
|
67 |
}
|
68 |
|
69 |
+
private function buildExactorAddressForAbstractAddress(Mage_Customer_Model_Address_Abstract $address){
|
70 |
$exactorAddress = new AddressType();
|
71 |
if ($address==null) return null;
|
72 |
// Set defaults
|
74 |
$exactorAddress->setFullName("Unknown Buyer");
|
75 |
//
|
76 |
$fullName = trim($address->getName());//trim($this->buildFullName($address->getFirstname(), $address->getLastname(), $address->getMiddlename()));
|
77 |
+
if (strlen($fullName)> self::PRICE_TYPE_DYNAMIC)
|
78 |
$exactorAddress->setFullName($fullName);
|
79 |
if ($address->getStreetFull() != null)
|
80 |
$exactorAddress->setStreet1($address->getStreetFull());
|
85 |
return $exactorAddress;
|
86 |
}
|
87 |
|
88 |
+
public function buildExactorAddressForOrderAddress(Mage_Sales_Model_Order_Address $address){
|
89 |
+
return $this->buildExactorAddressForAbstractAddress($address);
|
90 |
+
}
|
91 |
+
|
92 |
+
public function buildExactorAddressForQuoteAddress(Mage_Sales_Model_Quote_Address $address){
|
93 |
+
return $this->buildExactorAddressForAbstractAddress($address);
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @param Mage_Sales_Model_Quote_Item_Abstract $magentoItem
|
98 |
+
* @param Exactor_Core_Model_MerchantSettings $merchantSettings
|
99 |
+
* @return string
|
100 |
+
*/
|
101 |
+
public function getSKUForItem($magentoItem,
|
102 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
103 |
$sku='';
|
104 |
+
$product = $magentoItem->getProduct();
|
105 |
+
if ($product == null)
|
106 |
+
$product = Mage::getModel('catalog/product')
|
107 |
+
->setStoreId($magentoItem->getStoreId())
|
108 |
+
->load($magentoItem->getProductId());
|
109 |
switch ($merchantSettings->getSourceOfSKU()){
|
110 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_NONE:
|
111 |
$sku = '';
|
112 |
break;
|
113 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_SKU_FIELD:
|
114 |
+
$sku = $magentoItem->getSku();
|
115 |
break;
|
116 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_ATTRIBUTE_NAME:
|
117 |
$attributeSetName = 'Default';
|
118 |
try{
|
119 |
$attributeSetModel = Mage::getModel("eav/entity_attribute_set");
|
120 |
+
$attributeSetModel->load($product->getAttributeSetId());
|
121 |
$attributeSetName = $attributeSetModel->getAttributeSetName();
|
122 |
}catch(Exception $e){}
|
123 |
$sku = $attributeSetName;
|
124 |
break;
|
125 |
case Exactor_Core_Model_MerchantSettings::SKU_SOURCE_PRODUCT_CATEGORY:
|
126 |
+
$category = $product->getCategory();
|
127 |
if ($category != null)
|
128 |
$sku = $category->getName();
|
129 |
break;
|
131 |
/** @var Mage_Tax_Model_Mysql4_Class_Collection $taxClassCollection */
|
132 |
$taxClassCollection = Mage::getModel('tax/class')->getCollection();
|
133 |
/** @var Mage_Tax_Model_Class $taxClass */
|
134 |
+
$taxClass = $taxClassCollection->getItemById($product->getTaxClassId());
|
135 |
if ($taxClass == null) $sku = ''; else $sku = $taxClass->getClassName();
|
136 |
break;
|
137 |
}
|
138 |
+
return substr($sku, self::PRICE_TYPE_DYNAMIC, self::MAX_SKU_CODE_LENGTH); // Max length for SKU is 16 characters
|
139 |
}
|
140 |
|
141 |
private function isUSPSShipping($methodName){
|
148 |
return false;
|
149 |
}
|
150 |
|
151 |
+
public function getShippingLineItemForQuoteAddress(Mage_Sales_Model_Quote_Address $quoteAddress,
|
152 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
153 |
+
|
154 |
if ($quoteAddress->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_BILLING) return null; // There is no shipping fees there
|
155 |
+
if ($quoteAddress->getShippingAmount()== self::PRICE_TYPE_DYNAMIC) return null;
|
156 |
+
$shippingLineItem = $this->getShippingLineItem($merchantSettings, $quoteAddress->getShippingMethod(),
|
157 |
+
$quoteAddress->getShippingDescription(),
|
158 |
+
$quoteAddress->getShippingAmount(),
|
159 |
+
$quoteAddress->getShippingDiscountAmount());
|
160 |
+
return $shippingLineItem;
|
161 |
+
}
|
162 |
+
|
163 |
+
public function getShippingLineItemForCreditMemo(Mage_Sales_Model_Order_Creditmemo $creditMemo, Exactor_Core_Model_MerchantSettings $merchantSettings){
|
164 |
+
if ($creditMemo->getShippingAmount()== self::PRICE_TYPE_DYNAMIC) return null;
|
165 |
+
$lineItem = $this->getShippingLineItem($merchantSettings, $creditMemo->getOrder()->getShippingMethod(),
|
166 |
+
$creditMemo->getOrder()->getShippingDescription(),
|
167 |
+
$creditMemo->getShippingAmount());
|
168 |
+
// For refunds we shouldn't subtract handling amount
|
169 |
+
$lineItem->setGrossAmount($creditMemo->getShippingAmount());
|
170 |
+
return $lineItem;
|
171 |
+
}
|
172 |
+
|
173 |
+
private function getShippingLineItem(Exactor_Core_Model_MerchantSettings $merchantSettings,
|
174 |
+
$carrierName, $carrierDescription, $amount, $discount=0){
|
175 |
$shippingLineItem = new LineItemType();
|
176 |
+
$shippingLineItem->setDescription(self::MSG_SHIPPING_DESCRIPTION_PREFIX . $carrierDescription);
|
177 |
if (trim($shippingLineItem->getDescription())==''){
|
178 |
$shippingLineItem->setDescription(self::MSG_DEFAULT_SHIPPING_NAME);
|
179 |
+
}
|
180 |
// Get EUC code for shipping
|
181 |
$shippingEUC = self::EUC_SHIPPING_COMMON_CARRIER;
|
182 |
if ($merchantSettings->isShippingIncludeHandling()){
|
183 |
$shippingEUC = self::EUC_SHIPPING_AND_HANDLING;
|
184 |
+
}else if ($this->isUSPSShipping($carrierName)){
|
185 |
$shippingEUC = self::EUC_SHIPPING_USPS;
|
186 |
}
|
187 |
$shippingLineItem->setSKU($shippingEUC);
|
189 |
$shippingLineItem->setId(self::LINE_ITEM_ID_SHIPPING);
|
190 |
$shippingLineItem->setQuantity(1);
|
191 |
// If shipping doesn't include handling we should subtract handling from the total shipping amount
|
|
|
192 |
if (!$merchantSettings->isShippingIncludeHandling()){
|
193 |
+
$amount -= $this->getHandlingFeeByMethodName($carrierName);
|
194 |
}
|
195 |
$shippingLineItem->setGrossAmount($amount);
|
196 |
+
$this->applyDiscountToLineItem($shippingLineItem,$discount);
|
197 |
return $shippingLineItem;
|
198 |
}
|
199 |
|
200 |
+
|
201 |
+
|
202 |
/**
|
203 |
* Returns handling feed amount by given name, or 0 if there is no handling
|
204 |
* @param $name
|
205 |
* @return void
|
206 |
*/
|
207 |
private function getHandlingFeeByMethodName($name){
|
208 |
+
if (strpos($name, "_")) $name = substr($name, self::PRICE_TYPE_DYNAMIC,strpos($name, "_"));
|
209 |
+
if ($name == null) $name="";
|
210 |
// Fetch carriers information from Magento config to determine handling amount
|
211 |
$carriers = Mage::getStoreConfig('carriers');
|
212 |
+
if (!array_key_exists($name, $carriers)) return self::PRICE_TYPE_DYNAMIC;
|
213 |
foreach($carriers as $id => $carrier){
|
214 |
+
if (array_key_exists('handling_fee', $carrier)){
|
215 |
if ($id == $name)
|
216 |
return $carrier['handling_fee'];
|
217 |
}
|
218 |
}
|
219 |
+
return self::PRICE_TYPE_DYNAMIC;
|
220 |
}
|
221 |
|
222 |
+
public function getHandlingLineItem(Exactor_Core_Model_MerchantSettings $merchantSettings, $carrierName){
|
|
|
|
|
223 |
if ($merchantSettings->isShippingIncludeHandling()) return null; // Handling already included in the shipping
|
224 |
$handlingLineItem = new LineItemType();
|
225 |
$handlingLineItem->setId(self::LINE_ITEM_ID_HANDLING);
|
226 |
$handlingLineItem->setDescription(self::MSG_HANDLING_FEE);
|
227 |
$handlingLineItem->setSKU(self::EUC_HANDLING);
|
228 |
$handlingLineItem->setQuantity(1);
|
229 |
+
$handlingLineItem->setGrossAmount($this->getHandlingFeeByMethodName($carrierName));
|
230 |
+
if ($handlingLineItem->getGrossAmount()== self::PRICE_TYPE_DYNAMIC) return null;
|
231 |
return $handlingLineItem;
|
232 |
}
|
233 |
|
234 |
+
private function getHandlingLineItemForQuoteAddress(Mage_Sales_Model_Quote_Address $quoteAddress,
|
235 |
+
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
236 |
+
if ($quoteAddress->getAddressType() == Mage_Sales_Model_Quote_Address::TYPE_BILLING) return null; // There is no shipping fees there
|
237 |
+
return $this->getHandlingLineItem($merchantSettings, $quoteAddress->getShippingMethod());
|
238 |
+
}
|
239 |
+
|
240 |
/**
|
241 |
* @param \Mage_Sales_Model_Quote_Address_Item|\Mage_Sales_Model_Quote_Item $magentoItem
|
242 |
* @param Mage_Sales_Model_Quote_Address $quoteAddress
|
243 |
* @param Exactor_Core_Model_MerchantSettings $merchantSettings
|
244 |
* @return LineItemType
|
245 |
*/
|
246 |
+
public function buildLineItemForMagentoItem($magentoItem,
|
247 |
Mage_Sales_Model_Quote_Address $quoteAddress,
|
248 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
249 |
$lineItem = new LineItemType();
|
252 |
$lineItem->setGrossAmount($magentoItem->getBaseRowTotal());
|
253 |
else
|
254 |
$lineItem->setGrossAmount(0.0);
|
255 |
+
// We should exclude 0 amount items
|
256 |
+
if ($lineItem->getGrossAmount() == self::PRICE_TYPE_DYNAMIC) return null;
|
257 |
$lineItem->setQuantity($magentoItem->getTotalQty());
|
258 |
+
if ($magentoItem instanceof Mage_Sales_Model_Order_Creditmemo_Item){
|
259 |
+
$lineItem->setSKU($this->getSKUForItem($magentoItem->getOrderItem(), $merchantSettings));
|
260 |
+
}else{
|
261 |
+
$lineItem->setSKU($this->getSKUForItem($magentoItem, $merchantSettings));
|
262 |
+
}
|
263 |
$this->applyDiscountToLineItem($lineItem, $magentoItem->getDiscountAmount());
|
264 |
+
// Check if it is bundle or groped product
|
265 |
+
if (in_array($magentoItem->getProductType(), array(Mage_Catalog_Model_Product_Type::TYPE_BUNDLE))) {
|
266 |
+
if ($magentoItem->getProduct()->getPriceType() == self::PRICE_TYPE_DYNAMIC) {
|
267 |
+
$lineItem->setGrossAmount(self::PRICE_TYPE_DYNAMIC);
|
268 |
+
$lineItem->setDescription($lineItem->getDescription() . " :: Dynamic Price");
|
269 |
+
return null; // Doesn't show it in the Exactor transaction.
|
270 |
+
}
|
271 |
+
}
|
272 |
return $lineItem;
|
273 |
}
|
274 |
|
275 |
public function applyDiscountToLineItem(LineItemType &$item, $discountAmount=0){
|
276 |
+
if ($discountAmount> self::PRICE_TYPE_DYNAMIC){
|
277 |
$discountedLine = self::MSG_DISCOUNTED_BY . $discountAmount;
|
278 |
$item->setDescription($item->getDescription() . " ($discountedLine)");
|
279 |
$item->setGrossAmount($item->getGrossAmount() - $discountAmount);
|
280 |
}
|
281 |
}
|
282 |
|
283 |
+
private function getExemptionIdForQuoteAddress(Mage_Sales_Model_Quote_Address $quoteAddress,
|
284 |
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
285 |
$exemptionId = '';
|
286 |
if ($merchantSettings->getExemptionsSupported()){
|
290 |
return $exemptionId;
|
291 |
}
|
292 |
|
293 |
+
private function getExemptionIdForCreditMemo(Mage_Sales_Model_Order_Creditmemo $creditMemo,
|
294 |
+
Exactor_Core_Model_MerchantSettings $merchantSettings){
|
295 |
+
$exemptionId = '';
|
296 |
+
if ($merchantSettings->getExemptionsSupported()){
|
297 |
+
$customerExemptionId = $creditMemo->getOrder()->getCustomerTaxvat();
|
298 |
+
if ($customerExemptionId!=null) $exemptionId=$customerExemptionId;
|
299 |
+
}
|
300 |
+
return $exemptionId;
|
301 |
+
}
|
302 |
+
|
303 |
private function getCurrentCurrencyCode(Mage_Sales_Model_Quote_Address $quoteAddress){
|
304 |
$store = Mage::app()->getStore();
|
305 |
if ($quoteAddress->getQuote() != null && $quoteAddress->getQuote()->getStoreId() != null){
|
306 |
$store = $quoteAddress->getQuote()->getStore();
|
307 |
}
|
308 |
+
return $this->getCurrencyCodeForStore($store);
|
309 |
+
}
|
310 |
+
|
311 |
+
private function getCurrencyCodeForStore(Mage_Core_Model_Store $store){
|
312 |
+
$currency = 'USD';
|
313 |
+
if ($store != null){
|
314 |
+
$currency = $store->getBaseCurrencyCode()!=null ? $store->getBaseCurrencyCode() : $currency;
|
315 |
+
}
|
316 |
return $currency;
|
317 |
}
|
318 |
|
319 |
+
private function buildGiftCardLineItem($amount){
|
320 |
+
$lineItem = new LineItemType();
|
321 |
+
$lineItem->setGrossAmount($amount);
|
322 |
+
$lineItem->setQuantity(1);
|
323 |
+
$lineItem->setSKU(self::EUC_GIFT_CARD);
|
324 |
+
$lineItem->setDescription(self::MSG_GIFT_CARD_ITEM);
|
325 |
+
return $lineItem;
|
326 |
+
}
|
327 |
+
|
328 |
/**
|
329 |
* @param Mage_Sales_Model_Quote_Address $quoteAddress
|
330 |
* @param Exactor_Core_Model_MerchantSettings $merchantSettings
|
331 |
* @param bool $isMultishipping
|
332 |
+
* @param $isEstimation
|
333 |
* @return InvoiceRequestType
|
334 |
*/
|
335 |
public function buildInvoiceRequestForQuoteAddress(Mage_Sales_Model_Quote_Address $quoteAddress,
|
336 |
Exactor_Core_Model_MerchantSettings $merchantSettings,
|
337 |
+
$isMultishipping, $isEstimation){
|
338 |
// Building Invoice Parts
|
339 |
$shipToAddress = $this->buildExactorAddressForQuoteAddress($quoteAddress);
|
340 |
// Trying to find billing address in the quote
|
341 |
$billingAddress = $this->buildExactorAddressForQuoteAddress($quoteAddress->getQuote()->getBillingAddress());
|
342 |
+
|
343 |
if ($isEstimation) $shipToAddress->setFullName(self::MSG_ESTIMATION_REQUEST);
|
344 |
// If this is just tax estimation for not logged in user
|
345 |
// we just need to use shipping as billing
|
346 |
if ($isEstimation){
|
347 |
+
// It is possible that postal code or state will be missing on the tax estimation form
|
348 |
+
// In this case we will try to determine region basing on the given Postal Code
|
349 |
+
if (strlen(trim($shipToAddress->getStateOrProvince()))== self::PRICE_TYPE_DYNAMIC && strlen(trim($shipToAddress->getPostalCode()))!= self::PRICE_TYPE_DYNAMIC){
|
350 |
+
$shipToAddress->setStateOrProvince(RegionResolver::getInstance()->getStateOrProvinceByCode(trim($shipToAddress->getPostalCode())));
|
351 |
+
}
|
352 |
$billingAddress = $shipToAddress;
|
353 |
}
|
354 |
// If shipping info unavailable - fallback to billing information
|
365 |
$invoiceRequest->setExemptionId($this->getExemptionIdForQuoteAddress($quoteAddress, $merchantSettings));
|
366 |
// Line items list
|
367 |
$magentoItems = $quoteAddress->getAllItems();
|
368 |
+
$itemNum = self::PRICE_TYPE_DYNAMIC;
|
369 |
/**
|
370 |
* @var $magentoItem Mage_Sales_Model_Quote_Item
|
371 |
*/
|
372 |
foreach ($magentoItems as $magentoItem){
|
373 |
$exactorLineItem = $this->buildLineItemForMagentoItem($magentoItem, $quoteAddress, $merchantSettings);
|
374 |
+
if ($exactorLineItem == null) continue;
|
375 |
+
$exactorLineItem->setId(self::INDEXED_LINE_ITEM_ID_PREFIX . $magentoItem->getId());
|
376 |
// If this is non-multishipping request we should set
|
377 |
// ship to address to billing address for VIRTUAL ITEMS
|
378 |
if (!$isMultishipping){
|
385 |
}
|
386 |
$invoiceRequest->addLineItem($exactorLineItem);
|
387 |
}
|
388 |
+
// Gift Cards
|
389 |
+
if ($quoteAddress->getBaseGiftCardsAmount() != null && $quoteAddress->getBaseGiftCardsAmount() != self::PRICE_TYPE_DYNAMIC){
|
390 |
+
$invoiceRequest->addLineItem($this->buildGiftCardLineItem(-1 * $quoteAddress->getBaseGiftCardsAmount()));
|
391 |
+
}
|
392 |
+
// Shipping & Handling
|
393 |
+
$invoiceRequest->addLineItem($this->getShippingLineItemForQuoteAddress($quoteAddress, $merchantSettings));
|
394 |
+
$invoiceRequest->addLineItem($this->getHandlingLineItemForQuoteAddress($quoteAddress, $merchantSettings));
|
395 |
+
return $invoiceRequest;
|
396 |
+
}
|
397 |
+
|
398 |
+
|
399 |
+
|
400 |
+
/**Return invoice requests by credit memo. In case if credit memo contains adjustments - returns 2 separated invoices
|
401 |
+
* @param Mage_Sales_Model_Order_Creditmemo $creditMemo
|
402 |
+
* @param Exactor_Core_Model_MerchantSettings $merchantSettings
|
403 |
+
* @return array InvoiceRequestType
|
404 |
+
*/
|
405 |
+
public function buildInvoiceRequestsForCreditMemo(Mage_Sales_Model_Order_Creditmemo $creditMemo, Exactor_Core_Model_MerchantSettings $merchantSettings){
|
406 |
+
$result = array();
|
407 |
+
$invoiceRequest = new InvoiceRequestType();
|
408 |
+
$invoiceRequest->setBillTo($this->buildExactorAddressForOrderAddress($creditMemo->getBillingAddress()));
|
409 |
+
$invoiceRequest->setShipTo($this->buildExactorAddressForOrderAddress($creditMemo->getShippingAddress()));
|
410 |
+
$invoiceRequest->setShipFrom($merchantSettings->getExactorShippingAddress());
|
411 |
+
$invoiceRequest->setCurrencyCode($creditMemo->getOrder()->getOrderCurrencyCode());
|
412 |
+
$invoiceRequest->setPurchaseOrderNumber("Refund");
|
413 |
+
$invoiceRequest->setSaleDate(new DateTime("@".$creditMemo->getOrder()->getCreatedAtDate()->getTimestamp()));
|
414 |
+
$invoiceRequest->setExemptionId($this->getExemptionIdForCreditMemo($creditMemo, $merchantSettings));
|
415 |
+
// Line items
|
416 |
+
$magentoItems = $creditMemo->getAllItems();
|
417 |
+
foreach ($magentoItems as $magentoItem){
|
418 |
+
$exactorLineItem = $this->buildLineItemForMagentoItem($magentoItem, new Mage_Sales_Model_Quote_Address(), $merchantSettings);
|
419 |
+
if ($exactorLineItem != null){
|
420 |
+
$exactorLineItem->setQuantity($magentoItem->getQty());
|
421 |
+
}
|
422 |
+
$invoiceRequest->addLineItem($exactorLineItem);
|
423 |
+
}
|
424 |
// Shipping & Handling
|
425 |
+
$shippingLineItem = $this->getShippingLineItemForCreditMemo($creditMemo, $merchantSettings);
|
426 |
+
$handlingLineItem = null;
|
427 |
+
|
428 |
+
if ($shippingLineItem!=null) {
|
429 |
+
$handlingLineItem = $this->getHandlingLineItem($merchantSettings, $creditMemo->getOrder()->getShippingMethod());
|
430 |
+
if ($handlingLineItem!=null){
|
431 |
+
$delta = $creditMemo->getOrder()->getBaseShippingAmount() - $creditMemo->getOrder()->getBaseShippingRefunded() + $creditMemo->getBaseShippingAmount();
|
432 |
+
$shippingFactor = $creditMemo->getBaseShippingAmount() / $delta;
|
433 |
+
$handlingAmount = $handlingLineItem->getGrossAmount()*$shippingFactor;
|
434 |
+
$shippingAmount = $creditMemo->getBaseShippingAmount() - $handlingAmount;
|
435 |
+
// Update amounts
|
436 |
+
$shippingLineItem->setGrossAmount($creditMemo->getStore()->roundPrice($shippingAmount));
|
437 |
+
$handlingLineItem->setGrossAmount($creditMemo->getStore()->roundPrice($handlingAmount));
|
438 |
+
}
|
439 |
+
}
|
440 |
+
|
441 |
+
$invoiceRequest->addLineItem($shippingLineItem);
|
442 |
+
$invoiceRequest->addLineItem($handlingLineItem);
|
443 |
+
|
444 |
+
$result[] = $invoiceRequest;
|
445 |
+
// Adjustments
|
446 |
+
$adjustmentsItem = new LineItemType();
|
447 |
+
$adjustmentsItem->setId(self::LINE_ITEM_ID_ADJUSTMENTS);
|
448 |
+
$adjustmentsItem->setDescription(self::MSG_ADJUSTMENTS);
|
449 |
+
$adjustmentsItem->setQuantity(1);
|
450 |
+
$adjustmentsItem->setSKU(self::EUC_NON_TAXABLE);
|
451 |
+
$adjustmentsItem->setGrossAmount($creditMemo->getAdjustmentPositive()-$creditMemo->getAdjustmentNegative());
|
452 |
+
if ($adjustmentsItem->getGrossAmount() != self::PRICE_TYPE_DYNAMIC ||
|
453 |
+
$creditMemo->getBaseGiftCardsAmount() != null && $creditMemo->getBaseGiftCardsAmount() != self::PRICE_TYPE_DYNAMIC
|
454 |
+
){
|
455 |
+
$adjustmentInvoice = clone $invoiceRequest;
|
456 |
+
$adjustmentInvoice->setPurchaseOrderNumber(self::MSG_ADJUSTMENTS_REFUND);
|
457 |
+
$adjustmentInvoice->setLineItems(array());
|
458 |
+
if ($adjustmentsItem->getGrossAmount() != self::PRICE_TYPE_DYNAMIC){
|
459 |
+
$adjustmentInvoice->addLineItem($adjustmentsItem);
|
460 |
+
}
|
461 |
+
// Gift Cards
|
462 |
+
if ($creditMemo->getBaseGiftCardsAmount() != null && $creditMemo->getBaseGiftCardsAmount() != self::PRICE_TYPE_DYNAMIC){
|
463 |
+
$adjustmentInvoice->addLineItem($this->buildGiftCardLineItem(-1 * $creditMemo->getBaseGiftCardsAmount()));
|
464 |
+
}
|
465 |
+
$result[] = $adjustmentInvoice;
|
466 |
+
}
|
467 |
+
return $result;
|
468 |
+
}
|
469 |
+
|
470 |
+
public function buildInvoiceRequestForMagentoInvoice(){
|
471 |
+
$invoiceRequest = new InvoiceRequestType();
|
472 |
+
|
473 |
return $invoiceRequest;
|
474 |
}
|
475 |
+
|
476 |
}
|
app/code/local/Exactor/Tax/Model/Sales/Total/Quote/Tax.php
CHANGED
@@ -61,6 +61,7 @@ class Exactor_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Add
|
|
61 |
require_once($libDir . '/XmlProcessing.php');
|
62 |
require_once($libDir . '/ExactorDomainObjects.php');
|
63 |
require_once($libDir . '/ExactorCommons.php');
|
|
|
64 |
// Magento specific definitions
|
65 |
require_once($libDir . '/Magento.php');
|
66 |
require_once($libDir . '/config.php');
|
@@ -128,7 +129,7 @@ class Exactor_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Add
|
|
128 |
//return $this->processTaxCalculationFail('Missing or invalid Merchant Settings');
|
129 |
}
|
130 |
// Preparing Exactor Invoice Request
|
131 |
-
$invoiceRequest = $this->exactorMappingHelper->buildInvoiceRequestForQuoteAddress($address, $merchantSettings, $this->isMultishippingRequest());
|
132 |
$this->logger->trace('Invoice ' . serialize($invoiceRequest),'collect');
|
133 |
if ($invoiceRequest != null && $this->checkIfCalculationNeeded($invoiceRequest, $merchantSettings)){
|
134 |
// Sending to Exactor Tax Calculation Request to Exactor
|
@@ -170,6 +171,7 @@ class Exactor_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Add
|
|
170 |
foreach ($address->getAllItems() as $item){
|
171 |
$shippingTax -= $item->getTaxAmount();
|
172 |
}
|
|
|
173 |
// The following code is workaraund for the bug in Magento 1.6.2 - Tax applied to the QuoteAddress object
|
174 |
// can be missed by Magento for some reason. This issue can be reproduced in very trickily manner:
|
175 |
// 1. login
|
@@ -193,6 +195,16 @@ class Exactor_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Add
|
|
193 |
}
|
194 |
|
195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
196 |
/**
|
197 |
* Set tax amount for each item
|
198 |
* @param \Mage_Sales_Model_Quote_Address $address
|
@@ -205,7 +217,7 @@ class Exactor_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Add
|
|
205 |
* @var Mage_Sales_Model_Quote_Item $item
|
206 |
*/
|
207 |
foreach ($address->getAllItems() as $item){
|
208 |
-
$taxResultItem = $invoice->getItemById(Exactor_Tax_Helper_Mapping::INDEXED_LINE_ITEM_ID_PREFIX . $item->
|
209 |
// If there is no item in response - set tax to 0
|
210 |
if ($taxResultItem==null){
|
211 |
$item->setTaxAmount(0);
|
@@ -249,6 +261,7 @@ class Exactor_Tax_Model_Sales_Total_Quote_Tax extends Mage_Sales_Model_Quote_Add
|
|
249 |
*/
|
250 |
private function checkIfCalculationNeeded($invoiceRequest, $merchantSettings){
|
251 |
// Calculating digital signature for the current request
|
|
|
252 |
$taxRequest = ExactorConnectionFactory::getInstance()->buildRequest($merchantSettings->getMerchantID(), $merchantSettings->getUserID());
|
253 |
$taxRequest->addInvoiceRequest($invoiceRequest);
|
254 |
$signatureBuilder = new ExactorDigitalSignatureBuilder();
|
61 |
require_once($libDir . '/XmlProcessing.php');
|
62 |
require_once($libDir . '/ExactorDomainObjects.php');
|
63 |
require_once($libDir . '/ExactorCommons.php');
|
64 |
+
require_once($libDir . '/RegionResolver.php');
|
65 |
// Magento specific definitions
|
66 |
require_once($libDir . '/Magento.php');
|
67 |
require_once($libDir . '/config.php');
|
129 |
//return $this->processTaxCalculationFail('Missing or invalid Merchant Settings');
|
130 |
}
|
131 |
// Preparing Exactor Invoice Request
|
132 |
+
$invoiceRequest = $this->exactorMappingHelper->buildInvoiceRequestForQuoteAddress($address, $merchantSettings, $this->isMultishippingRequest(), $this->isEstimation());
|
133 |
$this->logger->trace('Invoice ' . serialize($invoiceRequest),'collect');
|
134 |
if ($invoiceRequest != null && $this->checkIfCalculationNeeded($invoiceRequest, $merchantSettings)){
|
135 |
// Sending to Exactor Tax Calculation Request to Exactor
|
171 |
foreach ($address->getAllItems() as $item){
|
172 |
$shippingTax -= $item->getTaxAmount();
|
173 |
}
|
174 |
+
$shippingTax = Mage::app()->getStore()->roundPrice($shippingTax);
|
175 |
// The following code is workaraund for the bug in Magento 1.6.2 - Tax applied to the QuoteAddress object
|
176 |
// can be missed by Magento for some reason. This issue can be reproduced in very trickily manner:
|
177 |
// 1. login
|
195 |
}
|
196 |
|
197 |
|
198 |
+
/**
|
199 |
+
* Returns true is request is just tax estimation
|
200 |
+
* @return bool
|
201 |
+
*/
|
202 |
+
private function isEstimation()
|
203 |
+
{
|
204 |
+
return strpos($this->session->getLastUrl(), "estimatePost") != false
|
205 |
+
|| strpos($this->session->getLastUrl(),"estimateUpdatePost") != false;
|
206 |
+
}
|
207 |
+
|
208 |
/**
|
209 |
* Set tax amount for each item
|
210 |
* @param \Mage_Sales_Model_Quote_Address $address
|
217 |
* @var Mage_Sales_Model_Quote_Item $item
|
218 |
*/
|
219 |
foreach ($address->getAllItems() as $item){
|
220 |
+
$taxResultItem = $invoice->getItemById(Exactor_Tax_Helper_Mapping::INDEXED_LINE_ITEM_ID_PREFIX . $item->getId());
|
221 |
// If there is no item in response - set tax to 0
|
222 |
if ($taxResultItem==null){
|
223 |
$item->setTaxAmount(0);
|
261 |
*/
|
262 |
private function checkIfCalculationNeeded($invoiceRequest, $merchantSettings){
|
263 |
// Calculating digital signature for the current request
|
264 |
+
if ($invoiceRequest == null || $invoiceRequest->getLineItems() == null) return false;
|
265 |
$taxRequest = ExactorConnectionFactory::getInstance()->buildRequest($merchantSettings->getMerchantID(), $merchantSettings->getUserID());
|
266 |
$taxRequest->addInvoiceRequest($invoiceRequest);
|
267 |
$signatureBuilder = new ExactorDigitalSignatureBuilder();
|
app/code/local/Exactor/Tax/etc/config.xml
CHANGED
@@ -28,7 +28,7 @@
|
|
28 |
<config>
|
29 |
<modules>
|
30 |
<Exactor_Tax>
|
31 |
-
<version>2012.
|
32 |
</Exactor_Tax>
|
33 |
</modules>
|
34 |
<global>
|
28 |
<config>
|
29 |
<modules>
|
30 |
<Exactor_Tax>
|
31 |
+
<version>2012.09.20</version>
|
32 |
</Exactor_Tax>
|
33 |
</modules>
|
34 |
<global>
|
app/design/adminhtml/default/default/template/ExactorSettings/settingsform.phtml
CHANGED
@@ -35,6 +35,16 @@
|
|
35 |
if ($accountSettings->getID() == null){
|
36 |
$accountSettings->setStoreViewID($this->getStoreViewId());
|
37 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
?>
|
39 |
<div class="content-header">
|
40 |
<table cellspacing="0" class="grid-header">
|
@@ -105,6 +115,19 @@
|
|
105 |
<td class="label"><?php echo $this->__('City')?> <span class="required">*</span></td>
|
106 |
<td class="input-ele"><input class="input-text validate-length required-entry" maxlength="128" name="exactordetailsform[City]" value="<?php echo $accountSettings->getCity();?>"/></td>
|
107 |
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
<tr>
|
109 |
<td class="label"><?php echo $this->__('State Or Province')?> <span class="required">*</span></td>
|
110 |
<td class="input-ele">
|
@@ -113,30 +136,17 @@
|
|
113 |
</select>
|
114 |
<script type="text/javascript">
|
115 |
//<![CDATA[
|
116 |
-
$('StateOrProvince_Id').setAttribute('defaultValue', "<?php echo $
|
117 |
//]]>
|
118 |
</script>
|
119 |
<input id="StateOrProvince" class="input-text validate-length"
|
120 |
value="<?php echo $accountSettings->getStateOrProvince() ?>"
|
121 |
maxlength="128" name="exactordetailsform[StateOrProvince]" />
|
122 |
</td>
|
123 |
-
</tr>
|
124 |
-
<tr>
|
125 |
-
<td class="label"><?php echo $this->__('Postal Code')?> <span class="required">*</span></td>
|
126 |
-
<td class="input-ele"><input class="input-text validate-zip required-entry" name="exactordetailsform[PostalCode]" value="<?php echo $accountSettings->getPostalCode();?>"/></td>
|
127 |
</tr>
|
128 |
<tr>
|
129 |
-
<td class="label"><?php echo $this->__('
|
130 |
-
|
131 |
-
<select id="Country" class="required-entry" name="exactordetailsform[Country]" STYLE="width: 250px">
|
132 |
-
<?php foreach ($country_lists as $country): ?>
|
133 |
-
<option value=<?php echo $country["value"] ?>
|
134 |
-
<?php if(($country["value"]==$accountSettings->getCountry()) || (trim($country["value"])=="US" && trim($accountSettings->getCountry())=="")): ?>
|
135 |
-
selected="true"<?php endif ?>><?php echo $country["label"]?>
|
136 |
-
</option>
|
137 |
-
<?php endforeach ?>
|
138 |
-
</select>
|
139 |
-
</td>
|
140 |
</tr>
|
141 |
</table>
|
142 |
</fieldset>
|
@@ -208,7 +218,7 @@
|
|
208 |
</div>
|
209 |
|
210 |
<script type="text/javascript">
|
211 |
-
new RegionUpdater('
|
212 |
<?php echo $this->helper('directory')->getRegionJson() ?>);
|
213 |
|
214 |
var editForm = new varienForm('edit_form');
|
35 |
if ($accountSettings->getID() == null){
|
36 |
$accountSettings->setStoreViewID($this->getStoreViewId());
|
37 |
}
|
38 |
+
$stateId = $regionInfo = Mage::getModel('directory/region')->getCollection()
|
39 |
+
->addFilter("code", $accountSettings->getStateOrProvince())
|
40 |
+
->addFilter("country_id", $accountSettings->getCountry())
|
41 |
+
->getFirstItem();
|
42 |
+
if ($stateId->hasData()) {
|
43 |
+
$stateId = $stateId->getRegionId();
|
44 |
+
} else {
|
45 |
+
$stateId = 0;
|
46 |
+
}
|
47 |
+
|
48 |
?>
|
49 |
<div class="content-header">
|
50 |
<table cellspacing="0" class="grid-header">
|
115 |
<td class="label"><?php echo $this->__('City')?> <span class="required">*</span></td>
|
116 |
<td class="input-ele"><input class="input-text validate-length required-entry" maxlength="128" name="exactordetailsform[City]" value="<?php echo $accountSettings->getCity();?>"/></td>
|
117 |
</tr>
|
118 |
+
<tr>
|
119 |
+
<td class="label"><?php echo $this->__('Country')?> <span class="required">*</span></td>
|
120 |
+
<td class="input-ele">
|
121 |
+
<select id="country" class="required-entry" name="exactordetailsform[Country]" STYLE="width: 250px">
|
122 |
+
<?php foreach ($country_lists as $country): ?>
|
123 |
+
<option value=<?php echo $country["value"] ?>
|
124 |
+
<?php if(($country["value"]==$accountSettings->getCountry()) || (trim($country["value"])=="US" && trim($accountSettings->getCountry())=="")): ?>
|
125 |
+
selected="true"<?php endif ?>><?php echo $country["label"]?>
|
126 |
+
</option>
|
127 |
+
<?php endforeach ?>
|
128 |
+
</select>
|
129 |
+
</td>
|
130 |
+
</tr>
|
131 |
<tr>
|
132 |
<td class="label"><?php echo $this->__('State Or Province')?> <span class="required">*</span></td>
|
133 |
<td class="input-ele">
|
136 |
</select>
|
137 |
<script type="text/javascript">
|
138 |
//<![CDATA[
|
139 |
+
$('StateOrProvince_Id').setAttribute('defaultValue', "<?php echo $stateId ?>");
|
140 |
//]]>
|
141 |
</script>
|
142 |
<input id="StateOrProvince" class="input-text validate-length"
|
143 |
value="<?php echo $accountSettings->getStateOrProvince() ?>"
|
144 |
maxlength="128" name="exactordetailsform[StateOrProvince]" />
|
145 |
</td>
|
|
|
|
|
|
|
|
|
146 |
</tr>
|
147 |
<tr>
|
148 |
+
<td class="label"><?php echo $this->__('Postal Code')?> <span class="required">*</span></td>
|
149 |
+
<td class="input-ele"><input class="input-text validate-zip-international required-entry" name="exactordetailsform[PostalCode]" value="<?php echo $accountSettings->getPostalCode();?>"/></td>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
</tr>
|
151 |
</table>
|
152 |
</fieldset>
|
218 |
</div>
|
219 |
|
220 |
<script type="text/javascript">
|
221 |
+
new RegionUpdater('country', 'StateOrProvince', 'StateOrProvince_Id',
|
222 |
<?php echo $this->helper('directory')->getRegionJson() ?>);
|
223 |
|
224 |
var editForm = new varienForm('edit_form');
|
lib/ExactorCommons/ExactorCommons.php
CHANGED
@@ -428,6 +428,7 @@ class ExactorDigitalSignatureBuilder{
|
|
428 |
$this->appendValue($invoice->getSaleDate());
|
429 |
$this->appendAddressFields($invoice->getShipTo());
|
430 |
$this->appendAddressFields($invoice->getShipFrom());
|
|
|
431 |
foreach ($invoice->getLineItems() as $lineItem){
|
432 |
$this->appendValue($lineItem->getGrossAmount());
|
433 |
}
|
@@ -655,6 +656,46 @@ class ExactorProcessingService{
|
|
655 |
return $response;
|
656 |
}
|
657 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
658 |
/**
|
659 |
* Fetch information about transaction from the internal database by given internal id
|
660 |
* and send refund request.
|
428 |
$this->appendValue($invoice->getSaleDate());
|
429 |
$this->appendAddressFields($invoice->getShipTo());
|
430 |
$this->appendAddressFields($invoice->getShipFrom());
|
431 |
+
if ($invoice->getLineItems() == null) return;
|
432 |
foreach ($invoice->getLineItems() as $lineItem){
|
433 |
$this->appendValue($lineItem->getGrossAmount());
|
434 |
}
|
656 |
return $response;
|
657 |
}
|
658 |
|
659 |
+
/**
|
660 |
+
* Performs partial refund basing on the InvoiceRequest information.
|
661 |
+
* Basically it just negate all amounts in the given invoice transaction and commits it.
|
662 |
+
* @param InvoiceRequestType $invoiceRequest
|
663 |
+
* @param DateTime $date
|
664 |
+
* @param string $invoiceNumber
|
665 |
+
* @return TaxResponseType
|
666 |
+
*/
|
667 |
+
public function partialRefund(InvoiceRequestType $invoiceRequest, DateTime $date, $invoiceNumber="unknown"){
|
668 |
+
$commitRequest = new CommitRequestType();
|
669 |
+
$commitRequest->setCommitDate($date);
|
670 |
+
$commitRequest->setInvoiceNumber($invoiceNumber);
|
671 |
+
// Negate all item amounts
|
672 |
+
foreach ($invoiceRequest->getLineItems() as $lineItem){
|
673 |
+
$lineItem->setGrossAmount(-1 * $lineItem->getGrossAmount());
|
674 |
+
}
|
675 |
+
$commitRequest->setInvoiceRequest($invoiceRequest);
|
676 |
+
$request = ExactorConnectionFactory::getInstance()->buildRequest($this->merchantId, $this->userId, $this->partnerId);
|
677 |
+
$request->addCommitRequest($commitRequest);
|
678 |
+
$response = ExactorConnectionFactory::getInstance()->buildExactorConnector()->sendRequest($request);
|
679 |
+
$signature='';
|
680 |
+
if ($response->hasErrors()){
|
681 |
+
if ($response->getFirstError()->getErrorCode() == ErrorResponseType::ERROR_INVALID_COMMIT_DATE){
|
682 |
+
$commitRequest->setCommitDate(new DateTime());
|
683 |
+
$response = ExactorConnectionFactory::getInstance()->buildExactorConnector()->sendRequest($request);
|
684 |
+
if ($response->hasErrors()){
|
685 |
+
$this->logger->error('Exactor Commit request failed. See debug info for details');
|
686 |
+
$this->pluginCallback->onCommitFail($signature, $response->getFirstError(), $commitRequest);
|
687 |
+
}
|
688 |
+
}else{
|
689 |
+
$this->logger->error('Exactor Commit request failed. See debug info for details');
|
690 |
+
$this->pluginCallback->onCommitFail($signature, $response->getFirstError(), $commitRequest);
|
691 |
+
}
|
692 |
+
}else{
|
693 |
+
$commitResponses = $response->getCommitResponses();
|
694 |
+
$this->pluginCallback->onCommitSuccess($signature, $commitResponses[0], $commitRequest, null);
|
695 |
+
}
|
696 |
+
return $response;
|
697 |
+
}
|
698 |
+
|
699 |
/**
|
700 |
* Fetch information about transaction from the internal database by given internal id
|
701 |
* and send refund request.
|
lib/ExactorCommons/ExactorDomainObjects.php
CHANGED
@@ -205,7 +205,7 @@ class AddressType extends XmlSerializationSupport {
|
|
205 |
*/
|
206 |
public function hasData(){
|
207 |
return //strlen(trim($this->getStreet1()))
|
208 |
-
// && strlen(trim($this->getCity()))
|
209 |
strlen(trim($this->getPostalCode()))
|
210 |
&& strlen(trim($this->getStateOrProvince()));
|
211 |
}
|
205 |
*/
|
206 |
public function hasData(){
|
207 |
return //strlen(trim($this->getStreet1()))
|
208 |
+
// && strlen(trim($this->getCity()))
|
209 |
strlen(trim($this->getPostalCode()))
|
210 |
&& strlen(trim($this->getStateOrProvince()));
|
211 |
}
|
lib/ExactorCommons/RegionResolver.php
ADDED
@@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* User: Dmitry Berezovsky
|
4 |
+
* Date: 7/31/12
|
5 |
+
* Time: 11:37 AM
|
6 |
+
*/
|
7 |
+
|
8 |
+
/**
|
9 |
+
* This helper class provides methods for determining region name or abbreviation by given postal code.
|
10 |
+
* Supports both of US and Canada postal codes.
|
11 |
+
*/
|
12 |
+
class RegionResolver {
|
13 |
+
const REGEX_VALID_ZIP = '/^\d{5}(-\d{4})?$/i';
|
14 |
+
// Each array contains 3 elements:
|
15 |
+
// C_USA_STATE_ABBREVIATION(0) - State abbreviation
|
16 |
+
// C_USA_ZIP_LOWER_BOUND(1) - Lower bound of the zip range
|
17 |
+
// C_USA_ZIP_UPPER_BOUND(2) - Upper bound of the zip range
|
18 |
+
const C_USA_STATE_ABBREVIATION = 0;
|
19 |
+
const C_USA_ZIP_LOWER_BOUND = 1;
|
20 |
+
const C_USA_ZIP_UPPER_BOUND = 2;
|
21 |
+
private $USA_CODES_TABLE = array(array("AL", 35004, 36925), array("AK", 99501, 99950), array("AZ", 85001, 86556),
|
22 |
+
array("AR", 71601, 72959), array("CA", 90001, 96162), array("CO", 80001, 81658),
|
23 |
+
array("CT", 6001, 6389), array("CT", 6401, 6928), array("DE", 19701, 19980),
|
24 |
+
array("DC", 20001, 20098), array("DC", 20201, 20586), array("DC", 20590, 20597),
|
25 |
+
array("DC", 20599, 20599), array("DC", 56901, 56972), array("FL", 32003, 33994),
|
26 |
+
array("FL", 34101, 34997), array("GA", 30002, 31999), array("GA", 39813, 39901),
|
27 |
+
array("HI", 96701, 96797), array("HI", 96801, 96898), array("ID", 83201, 83406),
|
28 |
+
array("ID", 83415, 83877), array("IL", 60001, 62999), array("IN", 46001, 47997),
|
29 |
+
array("IA", 50001, 52809), array("KS", 66002, 67954), array("KY", 40003, 42788),
|
30 |
+
array("LA", 70001, 71497), array("ME", 3901, 4992), array("MD", 20588, 20588),
|
31 |
+
array("MD", 20601, 21930), array("MA", 1001, 2791), array("MA", 5501, 5544),
|
32 |
+
array("MI", 48001, 49971), array("MN", 55001, 56763), array("MS", 38601, 39776),
|
33 |
+
array("MO", 63001, 65899), array("MT", 59001, 59937), array("NE", 68001, 69367),
|
34 |
+
array("NV", 88901, 89883), array("NH", 3031, 3897), array("NJ", 7001, 8989),
|
35 |
+
array("NM", 87001, 88439), array("NY", 501, 544), array("NY", 6390, 6390),
|
36 |
+
array("NY", 10001, 14925), array("NC", 27006, 28909), array("ND", 58001, 58856),
|
37 |
+
array("OH", 43001, 45999), array("OK", 73001, 73198), array("OK", 73401, 74966),
|
38 |
+
array("OR", 97001, 97920), array("PA", 15001, 19612), array("RI", 2801, 2940),
|
39 |
+
array("SC", 29001, 29945), array("SD", 57001, 57799), array("TN", 37010, 38589),
|
40 |
+
array("TX", 73301, 73344), array("TX", 75001, 79999), array("TX", 88510, 88595),
|
41 |
+
array("UT", 84001, 84791), array("VT", 5001, 5495), array("VT", 5601, 5907),
|
42 |
+
array("VA", 20101, 20198), array("VA", 20598, 20598), array("VA", 22003, 24658),
|
43 |
+
array("WA", 98001, 99403), array("WV", 24701, 26886), array("WI", 53001, 54990),
|
44 |
+
array("WY", 82001, 83128), array("WY", 83414, 83414), array("AS", 96799, 96799),
|
45 |
+
array("GU", 96910, 96932), array("MP", 96950, 96952), array("PR", 601, 795),
|
46 |
+
array("PR", 901, 988), array("VI", 801, 851), array("FM", 96941, 96944),
|
47 |
+
array("MH", 96960, 96970), array("PW", 96939, 96940), array("AA", 34002, 34099),
|
48 |
+
array("AE", 9002, 9898), array("AP", 96201, 96698));
|
49 |
+
const REGEX_VALID_CA_CODE = '/^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$/i';
|
50 |
+
// Each array contains 3 elements:
|
51 |
+
// C_CAN_REGION_ABBREVIATION(0) - Region abbreviation
|
52 |
+
// C_CAN_DISTRICT_IDS(1) - Array of the post district identifiers
|
53 |
+
// C_CAN_REGION_NAME(2) - Full region name
|
54 |
+
const C_CAN_REGION_ABBREVIATION = 0;
|
55 |
+
const C_CAN_DISTRICT_IDS = 1;
|
56 |
+
const C_CAN_REGION_NAME = 2;
|
57 |
+
private $CANADA_CODES_TABLE = array(array("NL",array("A"),"Newfoundland and Labrador"),
|
58 |
+
array("NS",array("B"),"Nova Scotia"),
|
59 |
+
array("PE",array("C"),"Prince Edward Island"),
|
60 |
+
array("NB",array("E"),"New Brunswick"),
|
61 |
+
array("QC",array("G","H","J"),"Quebec"),
|
62 |
+
array("ON",array("K","L","M","N","P"),"Ontario"),
|
63 |
+
array("MB",array("R"),"Manitoba"),
|
64 |
+
array("SK",array("S"),"Saskatchewan"),
|
65 |
+
array("AB",array("T"),"Alberta"),
|
66 |
+
array("BC",array("V"),"British Columbia"),
|
67 |
+
array("NT",array("X"),"Northwest Territories"),
|
68 |
+
array("YT",array("Y"),"Yukon")
|
69 |
+
);
|
70 |
+
|
71 |
+
protected static $instance;
|
72 |
+
static function __cmp_sort_zip_codes($a, $b){
|
73 |
+
if ($a[1] == $b[1]) return 0;
|
74 |
+
return ($a[1]>$b[1]) ? 1 : -1;
|
75 |
+
}
|
76 |
+
private function __construct(){
|
77 |
+
usort($this->USA_CODES_TABLE, "RegionResolver::__cmp_sort_zip_codes");
|
78 |
+
}
|
79 |
+
private function __clone() { }
|
80 |
+
private function __wakeup() { }
|
81 |
+
/**
|
82 |
+
* @static
|
83 |
+
* @return RegionResolver
|
84 |
+
*/
|
85 |
+
public static function getInstance() {
|
86 |
+
if ( is_null(self::$instance) ) {
|
87 |
+
self::$instance = new RegionResolver;
|
88 |
+
}
|
89 |
+
return self::$instance;
|
90 |
+
}
|
91 |
+
|
92 |
+
/**
|
93 |
+
* Returns true if given code is valid USA ZIP code(e.g "94105-0011" or "94105")
|
94 |
+
* @param $zip
|
95 |
+
* @return bool
|
96 |
+
*/
|
97 |
+
public function isValidUSAZip($zip){
|
98 |
+
return preg_match(self::REGEX_VALID_ZIP, $zip)>0;
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Returns true if given code is valid Canadian postal code("T2X 1V4" or "T2X1V4")
|
103 |
+
* @param $postalCode
|
104 |
+
* @return bool
|
105 |
+
*/
|
106 |
+
public function isValidCanadianPostalCode($postalCode){
|
107 |
+
return preg_match(self::REGEX_VALID_CA_CODE, $postalCode)>0;
|
108 |
+
}
|
109 |
+
|
110 |
+
private function find_in_array($array, $callback, $param){
|
111 |
+
$res = array();
|
112 |
+
foreach($array as $x){
|
113 |
+
if (call_user_func($callback,$x,$param)) $res[] = $x;
|
114 |
+
}
|
115 |
+
return $res;
|
116 |
+
}
|
117 |
+
|
118 |
+
static function __cmp_filter_usa_zip($element, $needle){
|
119 |
+
$intZip = intval($needle);
|
120 |
+
return ($intZip > $element[1] && $intZip < $element[2]) || $intZip == $element[1] || $intZip == $element[2];
|
121 |
+
}
|
122 |
+
|
123 |
+
public function getUSAStateByZip($zipCode){
|
124 |
+
if (!$this->isValidUSAZip($zipCode))
|
125 |
+
throw new InvalidArgumentException("Given code $zipCode is not valid USA ZIP code");
|
126 |
+
if (strpos($zipCode,'-'))
|
127 |
+
$zipCode = substr($zipCode, 0,strpos($zipCode, '-'));
|
128 |
+
$result = $this->find_in_array($this->USA_CODES_TABLE, "RegionResolver::__cmp_filter_usa_zip", $zipCode);
|
129 |
+
if (count($result)==0) return null;
|
130 |
+
$keys = array_keys($result);
|
131 |
+
return $result[$keys[0]][self::C_USA_STATE_ABBREVIATION];
|
132 |
+
}
|
133 |
+
|
134 |
+
static function __cmp_filter_ca_postal_code($element, $needle){
|
135 |
+
return in_array($needle,$element[1]);
|
136 |
+
}
|
137 |
+
|
138 |
+
public function getCanadianProvinceInfoByPostalCode($postalCode){
|
139 |
+
if (!$this->isValidCanadianPostalCode($postalCode)){
|
140 |
+
throw new InvalidArgumentException("Given code $postalCode is not valid Canadian postal code");
|
141 |
+
}
|
142 |
+
$districtId = strtoupper(substr($postalCode,0,1));
|
143 |
+
$result = $this->find_in_array($this->CANADA_CODES_TABLE, "RegionResolver::__cmp_filter_ca_postal_code", $districtId);
|
144 |
+
if (count($result)==0) return null;
|
145 |
+
$keys = array_keys($result);
|
146 |
+
return $result[$keys[0]];
|
147 |
+
}
|
148 |
+
|
149 |
+
public function getCanadianProvinceAbbrByPostalCode($postalCode){
|
150 |
+
$provinceInfo = $this->getCanadianProvinceInfoByPostalCode($postalCode);
|
151 |
+
if ($provinceInfo == null) return null;
|
152 |
+
return $provinceInfo[self::C_CAN_REGION_ABBREVIATION];
|
153 |
+
}
|
154 |
+
|
155 |
+
public function getCanadianProvinceNameByPostalCode($postalCode){
|
156 |
+
$provinceInfo = $this->getCanadianProvinceInfoByPostalCode($postalCode);
|
157 |
+
if ($provinceInfo == null) return null;
|
158 |
+
return $provinceInfo[self::C_CAN_REGION_NAME];
|
159 |
+
}
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Determines State or Province by given postal code. If cod if not valid USA or Canadian postal cod - returns null
|
163 |
+
* @param $postalCode
|
164 |
+
* @return USA State or name of the Canadian province
|
165 |
+
*/
|
166 |
+
public function getStateOrProvinceByCode($postalCode){
|
167 |
+
if ($this->isValidUSAZip($postalCode)){
|
168 |
+
return $this->getUSAStateByZip($postalCode);
|
169 |
+
}else if($this->isValidCanadianPostalCode($postalCode)) {
|
170 |
+
return $this->getCanadianProvinceNameByPostalCode($postalCode);
|
171 |
+
}else{
|
172 |
+
return null;
|
173 |
+
}
|
174 |
+
}
|
175 |
+
}
|
lib/ExactorCommons/config.php
CHANGED
@@ -6,6 +6,6 @@
|
|
6 |
*/
|
7 |
|
8 |
ExactorLoggingFactory::getInstance()->setup('MagentoLogger', IExactorLogger::TRACE);
|
9 |
-
ExactorConnectionFactory::getInstance()->setup('Magento','
|
10 |
ExactorProcessingServiceFactory::getInstance()->setup(new MagentoExactorCallback());
|
11 |
|
6 |
*/
|
7 |
|
8 |
ExactorLoggingFactory::getInstance()->setup('MagentoLogger', IExactorLogger::TRACE);
|
9 |
+
ExactorConnectionFactory::getInstance()->setup('Magento','v20120920');
|
10 |
ExactorProcessingServiceFactory::getInstance()->setup(new MagentoExactorCallback());
|
11 |
|
package.xml
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Mage_Exactor_Tax</name>
|
4 |
-
<version>2012.
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
<channel>community</channel>
|
@@ -10,11 +10,11 @@
|
|
10 |
<description>This module was developed to enable businesses to incorporate and benefit from the Exactor sales tax compliance service within their Magento shopping cart. Exactor presents a sales tax compliance module for (i) calculating sales tax within the e-commerce shopping process; and (ii) generating and filing sales tax returns in all US jurisdictions (state and local).This plug-in was developed to enable businesses to incorporate and benefit from the Exactor sales tax compliance service within their Magento shopping cart. 
|
11 |
Once installed, neither the merchant, nor the customer, need to perform any additional functions to obtain sales taxes. The taxes will be calculated and seamlessly displayed in the Magento shopping cart, and because the shopping cart communicates with the Exactor system, the ExactorFile module will be able to generate tax returns without the merchant having to transfer data from one system to another.
|
12 |
For additional information, please refer to the Exactor Magento User Guide that is attached to the plug-in, or which you can download directly from the Exactor control panel (navigate to Account Management Integration Points & PlugIns).</description>
|
13 |
-
<notes>Supported Magento 1.5.0.0 - 1.7.x</notes>
|
14 |
<authors><author><name>Exactor, Inc.</name><user>exactor</user><email>support@exactor.com</email></author></authors>
|
15 |
-
<date>2012-
|
16 |
-
<time>16:
|
17 |
-
<contents><target name="magelocal"><dir name="Exactor"><dir name="Core"><dir name="Helper"><file name="SessionCache.php" hash="
|
18 |
<compatible/>
|
19 |
<dependencies><required><php><min>5.0.0</min><max>6.0.0</max></php></required></dependencies>
|
20 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>Mage_Exactor_Tax</name>
|
4 |
+
<version>2012.09.20</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
|
7 |
<channel>community</channel>
|
10 |
<description>This module was developed to enable businesses to incorporate and benefit from the Exactor sales tax compliance service within their Magento shopping cart. Exactor presents a sales tax compliance module for (i) calculating sales tax within the e-commerce shopping process; and (ii) generating and filing sales tax returns in all US jurisdictions (state and local).This plug-in was developed to enable businesses to incorporate and benefit from the Exactor sales tax compliance service within their Magento shopping cart. 
|
11 |
Once installed, neither the merchant, nor the customer, need to perform any additional functions to obtain sales taxes. The taxes will be calculated and seamlessly displayed in the Magento shopping cart, and because the shopping cart communicates with the Exactor system, the ExactorFile module will be able to generate tax returns without the merchant having to transfer data from one system to another.
|
12 |
For additional information, please refer to the Exactor Magento User Guide that is attached to the plug-in, or which you can download directly from the Exactor control panel (navigate to Account Management Integration Points & PlugIns).</description>
|
13 |
+
<notes>Supported Magento 1.5.0.0 - 1.7.x, Magento Enterprise 1.8-1.12.x</notes>
|
14 |
<authors><author><name>Exactor, Inc.</name><user>exactor</user><email>support@exactor.com</email></author></authors>
|
15 |
+
<date>2012-09-21</date>
|
16 |
+
<time>16:32:09</time>
|
17 |
+
<contents><target name="magelocal"><dir name="Exactor"><dir name="Core"><dir name="Helper"><file name="SessionCache.php" hash="72692a33574f8ba2f1858e2e93aa4edf"/></dir><dir name="Model"><file name="ExactorTransaction.php" hash="852aa20f6e3b7aa0001439d4bffe9724"/><file name="MerchantSettings.php" hash="b4c2acde5dfa929e89ea7ec9fe0f1b2f"/><dir name="Mysql4"><dir name="ExactorTransaction"><file name="Collection.php" hash="c7b890b4d3ab35e65a3856ae0e2fdf72"/></dir><file name="ExactorTransaction.php" hash="c91aebaae767613acf1c439a8b513c3b"/><dir name="MerchantSettings"><file name="Collection.php" hash="c1593f52e582e601409c4651c37495af"/><file name="Collection.php~" hash="d360e202eb30432ac41dc023ce13ffc0"/></dir><file name="MerchantSettings.php" hash="8f22b76bb64cdc7b1deb6f0e38889905"/></dir><dir name="Type"><file name="Onepage.php" hash="2441fb08bbeb579831cea4d3fbd31104"/></dir></dir><dir name="etc"><file name="config.xml" hash="98ecc82a5f7b74ac0bfc0f7ab512afdb"/></dir></dir><dir name="ExactorSettings"><dir name="Block"><file name="Form.php" hash="7dcfb00922cfe305d8ae08cb20ca5e87"/></dir><dir name="Helper"><file name="Data.php" hash="a23bb9c251f0dbb77c107d01dde39e86"/><file name="VersionResolver.php" hash="14dce068dfe2a7d3364c4bd29e6f8431"/></dir><dir name="controllers"><dir name="Adminhtml"><file name="FormController.php" hash="bebd9e556ff2266f5208c950da3ade14"/></dir><file name="AjaxController.php" hash="c07aeeca00e1408e52945fc027569793"/><file name="IndexController.php" hash="f47cbc274dd68c57c30b60bbee69259e"/></dir><dir name="etc"><file name="config.xml" hash="6c2f28c302b359abd12565264fa23bc5"/></dir><dir name="sql"><dir name="ExactorSettings_setup"><file name="mysql4-install-14.04.2012.php" hash="f35af1e12921b57479cb4b5677937a0c"/></dir></dir></dir><dir name="Sales"><dir name="Model"><file name="Observer.php" hash="3bf71b114fd042f9da4cafd0e2f60712"/></dir><dir name="etc"><file name="config.xml" hash="621a49d9f295a607fadb1cd92a96cbe0"/></dir></dir><dir name="Tax"><dir name="Helper"><file name="Calculation.php" hash="29c5252bdd48b173c90588f449114024"/><file name="Mapping.php" hash="6246788c22bfbf4f26a38940fa392f92"/></dir><dir name="Model"><dir name="Sales"><dir name="Total"><dir name="Quote"><dir name="Nominal"><file name="Tax.php" hash="156eff380df5b16db55449759f193490"/></dir><file name="Tax.php" hash="2177508f9375ba7c250ae165a798de72"/></dir></dir></dir></dir><dir name="etc"><file name="config.xml" hash="d4bc1466549b6a860cdc6793103ebfb5"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="exactorsettings.xml" hash="3707eac08d2393c8796eebf1cf7a0bd9"/><file name="exactoronestepcheckout.xml" hash="9fdfa1db5e4e60b4eec8f348c10aab07"/></dir><dir name="template"><dir name="ExactorSettings"><file name="settingsform.phtml" hash="40d421317cee3a5a8df1dde2b223f7d9"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="exactoronestepcheckout.xml" hash="9fdfa1db5e4e60b4eec8f348c10aab07"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Exactor.xml" hash="e8997e8e36a265141b37790caaef39d6"/></dir></target><target name="mageweb"><dir name="js"><dir name="exactor"><file name="exactor.js" hash="5c23e40f4034e50a6e0df5b1c708b7e1"/></dir></dir></target><target name="magelib"><dir name="ExactorCommons"><file name="ExactorCommons.php" hash="8c1fb7bc67a16e47d99c957c5d19b4be"/><file name="ExactorDomainObjects.php" hash="28be782abfd7cf4bd4d23228ae97acc8"/><file name="Magento.php" hash="76da7333fe0692053a47f8564c7b513a"/><file name="RegionResolver.php" hash="2537638a7895a169cee4b1df786d22fb"/><file name="XmlProcessing.php" hash="383fd21839889d720e2094e83ccc7a2a"/><file name="config.php" hash="2d433e23d3b6588cc71806e5a2c1b6c7"/><file name="config.php~" hash="f12c65295b05793efd89dd64748282d1"/></dir></target></contents>
|
18 |
<compatible/>
|
19 |
<dependencies><required><php><min>5.0.0</min><max>6.0.0</max></php></required></dependencies>
|
20 |
</package>
|