spree_exactor 1.1.1.112920126 → 1.1.2.20130723
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile.lock +99 -149
- data/app/helpers/exactor_api_service.rb +6 -0
- data/app/helpers/spree_exactor_connector.rb +185 -46
- data/app/models/spree/adjustment_decorator.rb +17 -15
- data/app/models/spree/calculator/exactor_tax_calculator.rb +48 -42
- data/app/models/spree/order_decorator.rb +14 -45
- data/app/models/spree/order_updater_decorator.rb +61 -0
- data/app/models/spree/tax_rate_decorator.rb +1 -1
- data/app/views/spree/admin/exactor_settings/show.html.erb +8 -2
- data/config/locales/en.yml +1 -0
- data/lib/generators/spree_exactor/install/install_generator.rb +1 -0
- data/spree_exactor.gemspec +6 -9
- metadata +22 -79
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 27c250c6a204226c1171108f548cc42e1ca1a447
|
4
|
+
data.tar.gz: 0bec1e17ea37b1f5dc8788e6e01591f1e7c5c30e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2d21ce301473eede40265a1c6112271901eaa8e072dfdadb7699457f95fd3a513a8239c2d938038cc124a7fc847764328524f5487cad13406d491c38c20b5ce9
|
7
|
+
data.tar.gz: ce6aa31c4104787cbcdfc2db83620adf9145d1afb213ff5cb42832fa85fc0d10a37606f95a947b54c2d11a73d234a2b7efc99062e1e82e0efa641b3d47770128
|
data/Gemfile.lock
CHANGED
@@ -1,56 +1,57 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
spree_exactor (1.1.
|
5
|
-
|
4
|
+
spree_exactor (1.1.2.20130723)
|
5
|
+
rspec
|
6
|
+
spree_core (>= 2.0.0)
|
7
|
+
sqlite3
|
6
8
|
xml-simple
|
7
9
|
|
8
10
|
GEM
|
9
11
|
remote: http://rubygems.org/
|
10
12
|
specs:
|
11
|
-
actionmailer (3.2.
|
12
|
-
actionpack (= 3.2.
|
13
|
-
mail (~> 2.
|
14
|
-
actionpack (3.2.
|
15
|
-
activemodel (= 3.2.
|
16
|
-
activesupport (= 3.2.
|
13
|
+
actionmailer (3.2.13)
|
14
|
+
actionpack (= 3.2.13)
|
15
|
+
mail (~> 2.5.3)
|
16
|
+
actionpack (3.2.13)
|
17
|
+
activemodel (= 3.2.13)
|
18
|
+
activesupport (= 3.2.13)
|
17
19
|
builder (~> 3.0.0)
|
18
20
|
erubis (~> 2.7.0)
|
19
21
|
journey (~> 1.0.4)
|
20
|
-
rack (~> 1.4.
|
22
|
+
rack (~> 1.4.5)
|
21
23
|
rack-cache (~> 1.2)
|
22
24
|
rack-test (~> 0.6.1)
|
23
25
|
sprockets (~> 2.2.1)
|
24
26
|
active_utils (1.0.5)
|
25
27
|
activesupport (>= 2.3.11)
|
26
28
|
i18n
|
27
|
-
activemerchant (1.
|
29
|
+
activemerchant (1.34.1)
|
28
30
|
active_utils (>= 1.0.2)
|
29
|
-
activesupport (>= 2.3.
|
31
|
+
activesupport (>= 2.3.14)
|
30
32
|
builder (>= 2.0.0)
|
31
33
|
i18n
|
32
34
|
json (>= 1.5.1)
|
33
35
|
money
|
34
|
-
nokogiri
|
35
|
-
activemodel (3.2.
|
36
|
-
activesupport (= 3.2.
|
36
|
+
nokogiri (< 1.6.0)
|
37
|
+
activemodel (3.2.13)
|
38
|
+
activesupport (= 3.2.13)
|
37
39
|
builder (~> 3.0.0)
|
38
|
-
activerecord (3.2.
|
39
|
-
activemodel (= 3.2.
|
40
|
-
activesupport (= 3.2.
|
40
|
+
activerecord (3.2.13)
|
41
|
+
activemodel (= 3.2.13)
|
42
|
+
activesupport (= 3.2.13)
|
41
43
|
arel (~> 3.0.2)
|
42
44
|
tzinfo (~> 0.3.29)
|
43
|
-
activeresource (3.2.
|
44
|
-
activemodel (= 3.2.
|
45
|
-
activesupport (= 3.2.
|
46
|
-
activesupport (3.2.
|
47
|
-
i18n (
|
45
|
+
activeresource (3.2.13)
|
46
|
+
activemodel (= 3.2.13)
|
47
|
+
activesupport (= 3.2.13)
|
48
|
+
activesupport (3.2.13)
|
49
|
+
i18n (= 0.6.1)
|
48
50
|
multi_json (~> 1.0)
|
49
|
-
acts_as_list (0.
|
50
|
-
|
51
|
-
archive-tar-minitar (0.5.2)
|
51
|
+
acts_as_list (0.2.0)
|
52
|
+
activerecord (>= 3.0)
|
52
53
|
arel (3.0.2)
|
53
|
-
awesome_nested_set (2.1.
|
54
|
+
awesome_nested_set (2.1.5)
|
54
55
|
activerecord (>= 3.0.0)
|
55
56
|
aws-sdk (1.3.9)
|
56
57
|
httparty (~> 0.7)
|
@@ -58,174 +59,123 @@ GEM
|
|
58
59
|
nokogiri (>= 1.4.4)
|
59
60
|
uuidtools (~> 2.1)
|
60
61
|
builder (3.0.4)
|
61
|
-
cancan (1.6.
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
rack-test (>= 0.5.4)
|
67
|
-
selenium-webdriver (~> 2.0)
|
68
|
-
xpath (~> 0.1.4)
|
69
|
-
childprocess (0.3.6)
|
70
|
-
ffi (~> 1.0, >= 1.0.6)
|
71
|
-
cocaine (0.4.2)
|
72
|
-
columnize (0.3.6)
|
62
|
+
cancan (1.6.8)
|
63
|
+
climate_control (0.0.3)
|
64
|
+
activesupport (>= 3.0)
|
65
|
+
cocaine (0.5.1)
|
66
|
+
climate_control (>= 0.0.3, < 1.0)
|
73
67
|
deface (0.9.1)
|
74
68
|
nokogiri (~> 1.5.0)
|
75
69
|
rails (~> 3.1)
|
76
|
-
diff-lcs (1.
|
70
|
+
diff-lcs (1.2.4)
|
77
71
|
erubis (2.7.0)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
highline (1.6.11)
|
83
|
-
hike (1.2.1)
|
84
|
-
httparty (0.9.0)
|
72
|
+
ffaker (1.16.2)
|
73
|
+
highline (1.6.18)
|
74
|
+
hike (1.2.3)
|
75
|
+
httparty (0.11.0)
|
85
76
|
multi_json (~> 1.0)
|
86
|
-
multi_xml
|
77
|
+
multi_xml (>= 0.5.2)
|
87
78
|
i18n (0.6.1)
|
88
79
|
journey (1.0.4)
|
89
|
-
|
90
|
-
railties (>= 3.0, < 5.0)
|
91
|
-
thor (>= 0.14, < 2.0)
|
92
|
-
json (1.7.5)
|
80
|
+
json (1.8.0)
|
93
81
|
kaminari (0.13.0)
|
94
82
|
actionpack (>= 3.0.0)
|
95
83
|
activesupport (>= 3.0.0)
|
96
84
|
railties (>= 3.0.0)
|
97
|
-
|
98
|
-
addressable
|
99
|
-
websocket
|
100
|
-
linecache19 (0.5.13)
|
101
|
-
ruby_core_source (>= 0.1.4)
|
102
|
-
mail (2.4.4)
|
103
|
-
i18n (>= 0.4.0)
|
85
|
+
mail (2.5.4)
|
104
86
|
mime-types (~> 1.16)
|
105
87
|
treetop (~> 1.4.8)
|
106
|
-
mime-types (1.
|
107
|
-
money (5.
|
108
|
-
i18n (~> 0.
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
activerecord (>=
|
115
|
-
activesupport (>=
|
116
|
-
cocaine (
|
88
|
+
mime-types (1.23)
|
89
|
+
money (5.1.1)
|
90
|
+
i18n (~> 0.6.0)
|
91
|
+
multi_json (1.7.7)
|
92
|
+
multi_xml (0.5.4)
|
93
|
+
nokogiri (1.5.10)
|
94
|
+
paperclip (3.4.2)
|
95
|
+
activemodel (>= 3.0.0)
|
96
|
+
activerecord (>= 3.0.0)
|
97
|
+
activesupport (>= 3.0.0)
|
98
|
+
cocaine (~> 0.5.0)
|
117
99
|
mime-types
|
118
100
|
polyamorous (0.5.0)
|
119
101
|
activerecord (~> 3.0)
|
120
102
|
polyglot (0.3.3)
|
121
|
-
|
122
|
-
activesupport (>= 2.3.14)
|
123
|
-
multi_json (~> 1.0)
|
124
|
-
rack (1.4.1)
|
103
|
+
rack (1.4.5)
|
125
104
|
rack-cache (1.2)
|
126
105
|
rack (>= 0.4)
|
127
|
-
rack-ssl (1.3.
|
106
|
+
rack-ssl (1.3.3)
|
128
107
|
rack
|
129
108
|
rack-test (0.6.2)
|
130
109
|
rack (>= 1.0)
|
131
|
-
rails (3.2.
|
132
|
-
actionmailer (= 3.2.
|
133
|
-
actionpack (= 3.2.
|
134
|
-
activerecord (= 3.2.
|
135
|
-
activeresource (= 3.2.
|
136
|
-
activesupport (= 3.2.
|
110
|
+
rails (3.2.13)
|
111
|
+
actionmailer (= 3.2.13)
|
112
|
+
actionpack (= 3.2.13)
|
113
|
+
activerecord (= 3.2.13)
|
114
|
+
activeresource (= 3.2.13)
|
115
|
+
activesupport (= 3.2.13)
|
137
116
|
bundler (~> 1.0)
|
138
|
-
railties (= 3.2.
|
139
|
-
railties (3.2.
|
140
|
-
actionpack (= 3.2.
|
141
|
-
activesupport (= 3.2.
|
117
|
+
railties (= 3.2.13)
|
118
|
+
railties (3.2.13)
|
119
|
+
actionpack (= 3.2.13)
|
120
|
+
activesupport (= 3.2.13)
|
142
121
|
rack-ssl (~> 1.3.2)
|
143
122
|
rake (>= 0.8.7)
|
144
123
|
rdoc (~> 3.4)
|
145
124
|
thor (>= 0.14.6, < 2.0)
|
146
|
-
rake (10.0
|
147
|
-
ransack (0.7.
|
125
|
+
rake (10.1.0)
|
126
|
+
ransack (0.7.2)
|
148
127
|
actionpack (~> 3.0)
|
149
128
|
activerecord (~> 3.0)
|
150
129
|
polyamorous (~> 0.5.0)
|
151
|
-
rdoc (3.12)
|
130
|
+
rdoc (3.12.2)
|
152
131
|
json (~> 1.4)
|
153
|
-
rspec
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
rspec-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
columnize (>= 0.3.1)
|
166
|
-
linecache19 (>= 0.5.11)
|
167
|
-
ruby_core_source (>= 0.1.4)
|
168
|
-
ruby-debug19 (0.11.6)
|
169
|
-
columnize (>= 0.3.1)
|
170
|
-
linecache19 (>= 0.5.11)
|
171
|
-
ruby-debug-base19 (>= 0.11.19)
|
172
|
-
ruby_core_source (0.1.5)
|
173
|
-
archive-tar-minitar (>= 0.5.2)
|
174
|
-
rubyzip (0.9.9)
|
175
|
-
select2-rails (3.2.1)
|
176
|
-
thor (~> 0.14)
|
177
|
-
selenium-webdriver (2.26.0)
|
178
|
-
childprocess (>= 0.2.5)
|
179
|
-
libwebsocket (~> 0.1.3)
|
180
|
-
multi_json (~> 1.0)
|
181
|
-
rubyzip
|
182
|
-
spree_core (1.2.2)
|
183
|
-
activemerchant (= 1.28.0)
|
184
|
-
acts_as_list (= 0.1.4)
|
185
|
-
awesome_nested_set (= 2.1.4)
|
132
|
+
rspec (2.14.1)
|
133
|
+
rspec-core (~> 2.14.0)
|
134
|
+
rspec-expectations (~> 2.14.0)
|
135
|
+
rspec-mocks (~> 2.14.0)
|
136
|
+
rspec-core (2.14.4)
|
137
|
+
rspec-expectations (2.14.0)
|
138
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
139
|
+
rspec-mocks (2.14.1)
|
140
|
+
spree_core (2.0.3)
|
141
|
+
activemerchant (~> 1.31)
|
142
|
+
acts_as_list (= 0.2.0)
|
143
|
+
awesome_nested_set (= 2.1.5)
|
186
144
|
aws-sdk (~> 1.3.4)
|
187
|
-
cancan (= 1.6.
|
145
|
+
cancan (= 1.6.8)
|
188
146
|
deface (>= 0.9.0)
|
189
|
-
ffaker (~> 1.
|
190
|
-
highline (= 1.6.
|
191
|
-
|
147
|
+
ffaker (~> 1.16.1)
|
148
|
+
highline (= 1.6.18)
|
149
|
+
httparty (~> 0.11)
|
150
|
+
json (>= 1.7.7)
|
192
151
|
kaminari (= 0.13.0)
|
193
|
-
money (= 5.
|
194
|
-
paperclip (~>
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
stringex (~> 1.3.2)
|
152
|
+
money (= 5.1.1)
|
153
|
+
paperclip (~> 3.4.1)
|
154
|
+
rails (~> 3.2.13)
|
155
|
+
ransack (= 0.7.2)
|
156
|
+
state_machine (= 1.2.0)
|
157
|
+
stringex (~> 1.5.1)
|
158
|
+
truncate_html (= 0.9.2)
|
201
159
|
sprockets (2.2.2)
|
202
160
|
hike (~> 1.2)
|
203
161
|
multi_json (~> 1.0)
|
204
162
|
rack (~> 1.0)
|
205
163
|
tilt (~> 1.1, != 1.3.0)
|
206
|
-
sqlite3 (1.3.
|
207
|
-
state_machine (1.
|
208
|
-
stringex (1.
|
209
|
-
thor (0.
|
210
|
-
tilt (1.
|
211
|
-
treetop (1.4.
|
164
|
+
sqlite3 (1.3.7)
|
165
|
+
state_machine (1.2.0)
|
166
|
+
stringex (1.5.1)
|
167
|
+
thor (0.18.1)
|
168
|
+
tilt (1.4.1)
|
169
|
+
treetop (1.4.14)
|
212
170
|
polyglot
|
213
171
|
polyglot (>= 0.3.1)
|
214
|
-
|
215
|
-
|
216
|
-
|
172
|
+
truncate_html (0.9.2)
|
173
|
+
tzinfo (0.3.37)
|
174
|
+
uuidtools (2.1.4)
|
217
175
|
xml-simple (1.1.2)
|
218
|
-
xpath (0.1.4)
|
219
|
-
nokogiri (~> 1.3)
|
220
176
|
|
221
177
|
PLATFORMS
|
222
178
|
ruby
|
223
179
|
|
224
180
|
DEPENDENCIES
|
225
|
-
capybara (= 1.0.1)
|
226
|
-
factory_girl (~> 2.6.4)
|
227
|
-
ffaker
|
228
|
-
rspec-rails (~> 2.9)
|
229
|
-
ruby-debug19
|
230
181
|
spree_exactor!
|
231
|
-
sqlite3
|
@@ -14,6 +14,12 @@ module ExactorApi
|
|
14
14
|
end
|
15
15
|
request = create_request(taxRequest)
|
16
16
|
request.add_field("Content-Type","application/xml")
|
17
|
+
|
18
|
+
plugin_name = taxRequest.xmlattr_plugin
|
19
|
+
plugin_version = taxRequest.xmlattr_version
|
20
|
+
|
21
|
+
request.add_field("User-Agent", "#{plugin_name}-#{plugin_version}")
|
22
|
+
|
17
23
|
response = Net::HTTP.start(API_URI.hostname, 80) do |http|
|
18
24
|
http.request(request)
|
19
25
|
end
|
@@ -30,7 +30,7 @@ module SpreeExactorConnector
|
|
30
30
|
testInvoice.ShipTo=addressType
|
31
31
|
testInvoice.BillTo=addressType
|
32
32
|
testInvoice.SaleDate=Date.current.to_s
|
33
|
-
testLineItem = InvoiceRequest::LineItem.new(nil, "#{TEST_ITEM_DESRIPTION} #{PLUGIN_VERSION}"
|
33
|
+
testLineItem = InvoiceRequest::LineItem.new(nil, "#{TEST_ITEM_DESRIPTION} #{PLUGIN_VERSION}", 1, 0.0)
|
34
34
|
testInvoice.LineItem=testLineItem
|
35
35
|
testRequest.InvoiceRequest= testInvoice
|
36
36
|
testRequest.xmlattr_version=PLUGIN_VERSION
|
@@ -38,23 +38,36 @@ module SpreeExactorConnector
|
|
38
38
|
return exactorApi.send_request(testRequest)
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
41
|
def calculate_tax_for_order(order)
|
44
42
|
response = nil
|
45
43
|
if @settings.nil?
|
46
44
|
response = create_tax_response(0)
|
47
45
|
return response
|
48
46
|
end
|
49
|
-
taxRequest =
|
50
|
-
taxRequest.InvoiceRequest=InvoiceRequest.new
|
51
|
-
taxRequest.InvoiceRequest.ShipFrom=@settings.get_ship_from()
|
52
|
-
taxRequest.InvoiceRequest.LineItem=[]
|
53
|
-
map_order_to_invoice!(order, taxRequest.InvoiceRequest)
|
47
|
+
taxRequest = create_invoice_request_for_order(order)
|
54
48
|
exactorApi = ExactorApi::ExactorApiService.new
|
55
49
|
return map_calculation_response(exactorApi.send_request(taxRequest))
|
56
50
|
end
|
57
51
|
|
52
|
+
def calculate_hash(order)
|
53
|
+
if @settings.nil?
|
54
|
+
return ''
|
55
|
+
end
|
56
|
+
|
57
|
+
taxRequest = create_invoice_request_for_order(order)
|
58
|
+
|
59
|
+
invoice = taxRequest.InvoiceRequest
|
60
|
+
hash = '|' + invoice.ExemptionId
|
61
|
+
hash += '|' + calculate_hash_for_address(invoice.ShipFrom)
|
62
|
+
hash += '|' + calculate_hash_for_address(invoice.ShipTo)
|
63
|
+
hash += '|' + calculate_hash_for_address(invoice.BillTo)
|
64
|
+
hash += '|' + calculate_hash_for_address(invoice.BillTo)
|
65
|
+
invoice.LineItem.each do |line|
|
66
|
+
hash += '|' + calculate_hash_for_line_item(line)
|
67
|
+
end
|
68
|
+
Digest::MD5.hexdigest(hash)
|
69
|
+
end
|
70
|
+
|
58
71
|
def commit_transaction(order)
|
59
72
|
taxRequest = create_tax_request_skeleton()
|
60
73
|
taxRequest.CommitRequest=CommitRequest.new
|
@@ -100,8 +113,8 @@ module SpreeExactorConnector
|
|
100
113
|
def do_commit!(order)
|
101
114
|
response = commit_transaction(order)
|
102
115
|
if (response.is_valid)
|
103
|
-
order.update_column(:exactor_invoice_transaction,nil)
|
104
|
-
order.update_column(:exactor_commit_transaction,response.commit_id)
|
116
|
+
order.update_column(:exactor_invoice_transaction, nil)
|
117
|
+
order.update_column(:exactor_commit_transaction, response.commit_id)
|
105
118
|
else
|
106
119
|
order.errors[:base]<<"Tax calculation failure: #{response.error_code}:#{response.error_description}"
|
107
120
|
end
|
@@ -132,24 +145,24 @@ module SpreeExactorConnector
|
|
132
145
|
end
|
133
146
|
|
134
147
|
def do_checkout!(order)
|
135
|
-
|
148
|
+
if (can_be_handled?(Spree::ExactorSetting::COMMIT_OPTIONS::TRANSACTION_STATE, order))
|
136
149
|
do_commit!(order)
|
137
150
|
end
|
138
151
|
end
|
139
152
|
|
140
153
|
def do_payment_completed!(order)
|
141
154
|
if (can_be_handled?(Spree::ExactorSetting::COMMIT_OPTIONS::PAYMENT_STATE, order))
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
155
|
+
update_tax_if_needed(order)
|
156
|
+
resp = nil
|
157
|
+
if order.exactor_commit_transaction
|
158
|
+
resp = refund_transaction(order)
|
159
|
+
end
|
160
|
+
if (!resp or resp.is_valid)
|
161
|
+
resp = do_commit!(order)
|
162
|
+
end
|
163
|
+
if (!resp.is_valid)
|
164
|
+
order.current_payment.errors[:base]<<"Tax synchronization failure: #{resp.error_code}:#{resp.error_description}" unless order.current_payment.nil?
|
165
|
+
end
|
153
166
|
end
|
154
167
|
end
|
155
168
|
|
@@ -175,7 +188,6 @@ module SpreeExactorConnector
|
|
175
188
|
end
|
176
189
|
|
177
190
|
|
178
|
-
|
179
191
|
private
|
180
192
|
|
181
193
|
def can_be_handled?(commit_type, order)
|
@@ -222,13 +234,24 @@ module SpreeExactorConnector
|
|
222
234
|
return taxRequest
|
223
235
|
end
|
224
236
|
|
237
|
+
# @param [Spree::Order] order
|
238
|
+
# @return [TaxRequest]
|
239
|
+
def create_invoice_request_for_order(order)
|
240
|
+
taxRequest = create_tax_request_skeleton()
|
241
|
+
taxRequest.InvoiceRequest=InvoiceRequest.new
|
242
|
+
taxRequest.InvoiceRequest.ShipFrom=@settings.get_ship_from()
|
243
|
+
taxRequest.InvoiceRequest.LineItem=[]
|
244
|
+
map_order_to_invoice!(order, taxRequest.InvoiceRequest)
|
245
|
+
taxRequest
|
246
|
+
end
|
247
|
+
|
225
248
|
def map_from_spree_address(address)
|
226
249
|
exactor_address = AddressType.new
|
227
250
|
exactor_address.FullName="#{address.firstname} #{address.lastname}"
|
228
251
|
exactor_address.Street1=address.address1
|
229
252
|
exactor_address.Street2=address.address2
|
230
253
|
exactor_address.City=address.city.to_s
|
231
|
-
exactor_address.StateOrProvince=address.state_id.nil?() ?address.state_name : address.state.to_s()
|
254
|
+
exactor_address.StateOrProvince=address.state_id.nil?() ? address.state_name : address.state.to_s()
|
232
255
|
exactor_address.PostalCode=address.zipcode
|
233
256
|
exactor_address.Country=address.country
|
234
257
|
return exactor_address
|
@@ -236,33 +259,116 @@ module SpreeExactorConnector
|
|
236
259
|
|
237
260
|
def get_sku_according_to_settings(line_item)
|
238
261
|
sku_source = @settings.sku_source
|
239
|
-
|
240
|
-
|
262
|
+
sku = "";
|
263
|
+
if (sku_source == Spree::ExactorSetting::SKU_SOURCES::SKU_FIELD)
|
241
264
|
sku = line_item.variant.sku
|
242
265
|
elsif (sku_source == Spree::ExactorSetting::SKU_SOURCES::TAX_CATEGORY)
|
243
266
|
sku = line_item.product.tax_category.name unless line_item.product.tax_category.nil?
|
244
267
|
end
|
245
|
-
|
268
|
+
return sku
|
246
269
|
end
|
247
270
|
|
248
|
-
def map_from_spree_lineitem(line_item)
|
271
|
+
def map_from_spree_lineitem(line_item, quantity_override = nil, package_id = nil)
|
249
272
|
exactor_line = InvoiceRequest::LineItem.new
|
250
273
|
exactor_line.SKU=get_sku_according_to_settings(line_item)
|
251
274
|
exactor_line.Description=line_item.product.description
|
252
|
-
|
253
|
-
|
254
|
-
|
275
|
+
if quantity_override.nil?
|
276
|
+
exactor_line.Quantity=line_item.quantity
|
277
|
+
exactor_line.GrossAmount=line_item.amount()
|
278
|
+
else
|
279
|
+
exactor_line.Quantity=quantity_override
|
280
|
+
exactor_line.GrossAmount=quantity_override * line_item.price
|
281
|
+
end
|
282
|
+
if package_id.nil? then
|
283
|
+
exactor_line.xmlattr_id= "_#{line_item.id}"
|
284
|
+
else
|
285
|
+
exactor_line.xmlattr_id= "_#{package_id}_#{line_item.id}"
|
286
|
+
end
|
255
287
|
return exactor_line
|
256
288
|
end
|
257
289
|
|
290
|
+
|
291
|
+
# @param [Spree::StockLocation] stock_location
|
292
|
+
# @param [AddressType] fallback_address
|
293
|
+
# @return [AddressType]
|
294
|
+
def map_from_stock_location(stock_location, fallback_address)
|
295
|
+
|
296
|
+
|
297
|
+
exactor_address = AddressType.new
|
298
|
+
exactor_address.FullName=fallback_address.FullName
|
299
|
+
exactor_address.Street1=stock_location.address1
|
300
|
+
exactor_address.Street2=stock_location.address2
|
301
|
+
exactor_address.City=stock_location.city.to_s
|
302
|
+
exactor_address.StateOrProvince=stock_location.state_id.nil?() ? stock_location.state_name : stock_location.state.to_s()
|
303
|
+
exactor_address.PostalCode=stock_location.zipcode
|
304
|
+
exactor_address.Country=stock_location.country
|
305
|
+
if exactor_address.Street1.nil? ||
|
306
|
+
exactor_address.City.nil? ||
|
307
|
+
exactor_address.StateOrProvince.nil? ||
|
308
|
+
exactor_address.PostalCode.nil?
|
309
|
+
return nil
|
310
|
+
end
|
311
|
+
|
312
|
+
return exactor_address
|
313
|
+
end
|
314
|
+
|
258
315
|
def map_order_to_invoice!(order, invoice)
|
259
316
|
invoice.ShipTo=map_from_spree_address(order.ship_address)
|
260
317
|
invoice.BillTo=map_from_spree_address(order.bill_address)
|
261
|
-
|
262
|
-
|
318
|
+
|
319
|
+
|
320
|
+
shipment_amounts = Hash.new(0)
|
321
|
+
shipment_addresses = Hash.new
|
322
|
+
shipment_quantities = Hash.new(0)
|
323
|
+
|
324
|
+
variant2line = Hash.new
|
325
|
+
order.line_items.each { |line_item| variant2line[line_item.variant_id] = line_item }
|
326
|
+
|
327
|
+
order.shipments.each do |shipment|
|
328
|
+
stockAddress = map_from_stock_location(shipment.stock_location, invoice.ShipFrom)
|
329
|
+
|
330
|
+
shipment.manifest.each do |item|
|
331
|
+
line_item = variant2line[item.variant.id]
|
332
|
+
# line item collection is fresher then manifest collection. User can remove line item but it will remain in the manifest collection!
|
333
|
+
unless line_item.nil?
|
334
|
+
exactor_line = map_from_spree_lineitem(
|
335
|
+
line_item,
|
336
|
+
item.quantity,
|
337
|
+
shipment.stock_location_id
|
338
|
+
)
|
339
|
+
exactor_line.ShipFrom = stockAddress
|
340
|
+
invoice.LineItem << exactor_line
|
341
|
+
end
|
342
|
+
end
|
343
|
+
# using stock_location_id instead of shipment_id is a workaround. Spree recreates shipments on delivery page.
|
344
|
+
# collect shipment amounts to create shipping items in the future
|
345
|
+
shipment_amounts[shipment.stock_location_id] = shipment.cost
|
346
|
+
shipment_addresses[shipment.stock_location_id] = stockAddress
|
347
|
+
shipment_quantities[shipment.stock_location_id] += 1
|
348
|
+
end
|
349
|
+
shipment_amounts.each do |id, amount|
|
350
|
+
shipment_quantities[id].times do
|
351
|
+
shipping_line_item = add_shipping_lineitem(amount, id)
|
352
|
+
shipping_line_item.ShipFrom = shipment_addresses[id]
|
353
|
+
invoice.LineItem.push(shipping_line_item)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
# check if order has free shipping adjustment
|
358
|
+
if order.adjustments.find_all { |adjustment| adjustment.originator.present? && adjustment.eligible? && adjustment.originator.calculator.is_a?(Spree::Calculator::FreeShipping) }.any?
|
359
|
+
shipment_amounts.each do |id, amount|
|
360
|
+
shipment_quantities[id].times do
|
361
|
+
free_shipping_line_item = add_free_shipping_lineitem(amount, id)
|
362
|
+
free_shipping_line_item.ShipFrom = shipment_addresses[id]
|
363
|
+
invoice.LineItem << free_shipping_line_item
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
263
368
|
index=0
|
264
369
|
order.adjustments.each do |adjustment|
|
265
|
-
|
370
|
+
|
371
|
+
line_item = map_adjustment_as_lineitem(adjustment, index)
|
266
372
|
if line_item
|
267
373
|
index+=1
|
268
374
|
invoice.LineItem << line_item
|
@@ -270,20 +376,37 @@ module SpreeExactorConnector
|
|
270
376
|
end
|
271
377
|
invoice.SaleDate=Date.current.to_s
|
272
378
|
invoice.PurchaseOrderNumber=order.number.to_s
|
273
|
-
|
379
|
+
unless order.user.anonymous?
|
274
380
|
invoice.ExemptionId=order.user.exactor_exemption_id
|
275
381
|
end
|
276
382
|
return invoice
|
277
383
|
end
|
278
384
|
|
385
|
+
def add_free_shipping_lineitem(shipping_amount, stock = nil)
|
386
|
+
exactor_line = InvoiceRequest::LineItem.new
|
387
|
+
exactor_line.SKU=@settings.shipping_include_handling ? SHIPPING_EUC_WITH_HANDLING : SHIPPING_EUC_NO_HANDLING
|
388
|
+
exactor_line.Description="Free shipping"
|
389
|
+
exactor_line.Quantity=1
|
390
|
+
exactor_line.GrossAmount=shipping_amount * -1
|
391
|
+
if stock.nil?
|
392
|
+
exactor_line.xmlattr_id="FREE_SHIPPING"
|
393
|
+
else
|
394
|
+
exactor_line.xmlattr_id="FREE_SHIPPING_#{stock}"
|
395
|
+
end
|
396
|
+
return exactor_line
|
397
|
+
end
|
279
398
|
|
280
|
-
def add_shipping_lineitem(shipping_amount)
|
399
|
+
def add_shipping_lineitem(shipping_amount, stock = nil)
|
281
400
|
exactor_line = InvoiceRequest::LineItem.new
|
282
401
|
exactor_line.SKU=@settings.shipping_include_handling ? SHIPPING_EUC_WITH_HANDLING : SHIPPING_EUC_NO_HANDLING
|
283
402
|
exactor_line.Description="Shipping"
|
284
403
|
exactor_line.Quantity=1
|
285
404
|
exactor_line.GrossAmount=shipping_amount
|
286
|
-
|
405
|
+
if stock.nil?
|
406
|
+
exactor_line.xmlattr_id="SHIPPING"
|
407
|
+
else
|
408
|
+
exactor_line.xmlattr_id="SHIPPING_#{stock}"
|
409
|
+
end
|
287
410
|
return exactor_line
|
288
411
|
end
|
289
412
|
|
@@ -298,20 +421,15 @@ module SpreeExactorConnector
|
|
298
421
|
|
299
422
|
def map_adjustment_as_lineitem(adjustment, index)
|
300
423
|
#filters tax and shipping
|
301
|
-
if adjustment.originator.present? and (adjustment.originator.is_a?(Spree::TaxRate) or adjustment.originator.is_a?(Spree::ShippingMethod))
|
302
|
-
|
424
|
+
if adjustment.originator.present? and (adjustment.originator.is_a?(Spree::TaxRate) or adjustment.originator.is_a?(Spree::ShippingMethod) or adjustment.originator.calculator.is_a?(Spree::Calculator::FreeShipping))
|
425
|
+
return nil
|
303
426
|
end
|
304
427
|
#filter non-eligible adjustments
|
305
428
|
return nil unless adjustment.eligible?
|
306
429
|
amount = adjustment.amount
|
307
430
|
euc=amount<0 ? DISCOUNT_EUC : MARKUP_EUC
|
308
|
-
description=
|
309
|
-
|
310
|
-
amount = -1*adjustment.source.ship_total
|
311
|
-
euc=@settings.shipping_include_handling ? SHIPPING_EUC_WITH_HANDLING : SHIPPING_EUC_NO_HANDLING
|
312
|
-
description="Free shipping"
|
313
|
-
end
|
314
|
-
exactor_line = InvoiceRequest::LineItem.new(euc,description,1,amount)
|
431
|
+
description= "Adjustment"
|
432
|
+
exactor_line = InvoiceRequest::LineItem.new(euc, description, 1, amount)
|
315
433
|
exactor_line.xmlattr_id="ADJUSTMENT_#{index}"
|
316
434
|
return exactor_line
|
317
435
|
end
|
@@ -376,5 +494,26 @@ module SpreeExactorConnector
|
|
376
494
|
end
|
377
495
|
end
|
378
496
|
|
497
|
+
# @param [AddressType] address
|
498
|
+
def calculate_hash_for_address(address)
|
499
|
+
if (address.nil?)
|
500
|
+
return ''
|
501
|
+
end
|
502
|
+
address_line1 = "#{address.FullName}|#{address.Street1.to_s.gsub(/\s+/, "")}|#{address.Street2.to_s.gsub(/\s+/, "")}|#{address.City}"
|
503
|
+
address_line2= "#{address.StateOrProvince}|#{address.PostalCode}|#{address.Country}"
|
504
|
+
return "#{address_line1}|#{address_line2}".downcase()
|
505
|
+
end
|
506
|
+
|
507
|
+
# @param [InvoiceRequest::LineItem] line
|
508
|
+
def calculate_hash_for_line_item(line)
|
509
|
+
hash = '|' + calculate_hash_for_address(line.ShipFrom)
|
510
|
+
hash += '|' + calculate_hash_for_address(line.ShipTo)
|
511
|
+
hash += '|' + calculate_hash_for_address(line.BillTo)
|
512
|
+
hash += '|' + line.SKU
|
513
|
+
hash += '|' + line.xmlattr_id.to_s
|
514
|
+
hash += '|' + line.Quantity.to_s
|
515
|
+
hash += '|' + line.GrossAmount.to_s
|
516
|
+
end
|
517
|
+
|
379
518
|
end
|
380
519
|
end
|
@@ -1,19 +1,4 @@
|
|
1
1
|
module Spree
|
2
|
-
class Adjustment
|
3
|
-
alias :super_update! :update!
|
4
|
-
|
5
|
-
#Spree sometimes lock adjustments. We will make to calculate Exactor Tax anyway!
|
6
|
-
def update!(src = nil)
|
7
|
-
if originator.present? and originator.is_a?(TaxRate) and originator.is_exactor_default?
|
8
|
-
self.locked = false
|
9
|
-
self.label = "Sales Tax"
|
10
|
-
self.update_attribute_without_callbacks(:label, label)
|
11
|
-
end
|
12
|
-
super_update!(src)
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
2
|
Adjustment.class_eval do
|
18
3
|
after_save :on_save
|
19
4
|
after_destroy :on_destroy
|
@@ -38,4 +23,21 @@ module Spree
|
|
38
23
|
adjustable.on_update()
|
39
24
|
end
|
40
25
|
end
|
26
|
+
class Adjustment
|
27
|
+
|
28
|
+
alias :super_update! :update!
|
29
|
+
|
30
|
+
#Spree sometimes lock adjustments. We will make to calculate Exactor Tax anyway!
|
31
|
+
def update!
|
32
|
+
if originator.present? and originator.is_a?(TaxRate) and originator.is_exactor_default?
|
33
|
+
self.state = "open"
|
34
|
+
self.label = "Sales Tax"
|
35
|
+
self.update_attribute_without_callbacks(:label, label)
|
36
|
+
end
|
37
|
+
super_update!
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
41
43
|
end
|
@@ -7,38 +7,13 @@ class Spree::Calculator::ExactorTaxCalculator < Spree::Calculator
|
|
7
7
|
"Exactor sales tax compliance provider"
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
address_line2= "#{address.state.to_s}|#{address.state_name.to_s.strip()}|#{address.zipcode}|#{address.country.to_s.strip}"
|
13
|
-
return "#{address_line1}|#{address_line2}".downcase()
|
14
|
-
end
|
15
|
-
|
16
|
-
def calculate_hash_from_items(items)
|
17
|
-
result = ""
|
18
|
-
items.each { |item| result+="|#{item.quantity}|#{item.price}|" }
|
19
|
-
return result
|
20
|
-
end
|
21
|
-
|
22
|
-
def calc_adjustment_amount(computable)
|
23
|
-
amount=0
|
24
|
-
computable.adjustments.each do |adjustment|
|
25
|
-
if ! adjustment.originator.present? or (adjustment.originator.present? and (!adjustment.originator.is_a?(Spree::TaxRate)))
|
26
|
-
if adjustment.eligible?
|
27
|
-
amount+=adjustment.amount
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
return amount
|
32
|
-
end
|
10
|
+
# @param [SpreeExactorConnector::SpreeExactorConnector] exactor
|
11
|
+
def is_needed_to_calculate_tax?(computable, exactor)
|
33
12
|
|
34
|
-
|
35
|
-
|
36
|
-
amounts = "#{calculate_hash_from_items(order.line_items)}|#{order.ship_total}|#{calc_adjustment_amount(order)}"
|
37
|
-
return Digest::MD5.hexdigest("#{addresses}|#{amounts}")
|
38
|
-
end
|
13
|
+
# don't try to calculate hash for partially formed order
|
14
|
+
return false unless is_full?(computable)
|
39
15
|
|
40
|
-
|
41
|
-
order_hash = calculate_hash(computable)
|
16
|
+
order_hash = exactor.calculate_hash(computable)
|
42
17
|
current_order_hash = Spree::Order.find(computable.id).exactor_order_hash_sum
|
43
18
|
result = order_hash!=current_order_hash
|
44
19
|
if result
|
@@ -48,29 +23,38 @@ class Spree::Calculator::ExactorTaxCalculator < Spree::Calculator
|
|
48
23
|
end
|
49
24
|
|
50
25
|
def update_line_items_with_tax_info(computable, response)
|
51
|
-
|
52
|
-
|
26
|
+
variant2line = Hash.new
|
27
|
+
computable.line_items.each { |line_item| variant2line[line_item.variant_id] = line_item }
|
28
|
+
|
29
|
+
line2tax = Hash.new(0)
|
30
|
+
|
31
|
+
computable.shipments.each do |shipment|
|
32
|
+
shipment.manifest.each do |item|
|
33
|
+
line = variant2line[item.variant.id]
|
34
|
+
# line item collection is fresher then manifest collection. User can remove line item but it will remain in the manifest collection!
|
35
|
+
unless line.nil?
|
36
|
+
line2tax[line] += response.get_line_item_tax("_#{shipment.stock_location_id}_#{line.id}")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
line2tax.each do |line_item, tax|
|
42
|
+
line_item.update_attribute_without_callbacks(:exactor_inline_tax, tax)
|
53
43
|
end
|
54
44
|
end
|
55
45
|
|
56
46
|
def compute(computable=nil)
|
57
47
|
if computable
|
58
|
-
settings =
|
48
|
+
settings = Spree::ExactorSetting.get_settings
|
59
49
|
if settings and (Date.current < settings.effective_date)
|
60
50
|
return 0
|
61
51
|
end
|
62
|
-
if (!computable.line_items.empty? and !computable.
|
63
|
-
#Workaroud of double request to Exactor: without shipping cost and with included shipping cost.
|
64
|
-
#we need to return at least any non-zero value in order to have tax adjustment created. When we will have shipment
|
65
|
-
#we will send real transaction to Exactor
|
66
|
-
if computable.adjustments.shipping.empty? and !computable.completed?
|
67
|
-
return 0.001
|
68
|
-
end
|
52
|
+
if (!computable.line_items.empty? and !computable.shipments.empty?) or computable.completed?
|
69
53
|
exactor = SpreeExactorConnector::SpreeExactorConnector.new
|
70
|
-
if is_needed_to_calculate_tax?(computable)
|
54
|
+
if is_needed_to_calculate_tax?(computable, exactor)
|
71
55
|
response = exactor.calculate_tax_for_order(computable)
|
72
56
|
if response.is_valid
|
73
|
-
computable.
|
57
|
+
computable.update_attribute_without_callbacks(:exactor_invoice_transaction, response.invoice_id)
|
74
58
|
update_line_items_with_tax_info(computable, response)
|
75
59
|
return response.total_tax
|
76
60
|
else
|
@@ -84,4 +68,26 @@ class Spree::Calculator::ExactorTaxCalculator < Spree::Calculator
|
|
84
68
|
end
|
85
69
|
end
|
86
70
|
|
71
|
+
# Whether this order is fully formed and ready for tax calculation.
|
72
|
+
# @param [Spree::Order] order
|
73
|
+
# @return [Boolean]
|
74
|
+
def is_full?(order)
|
75
|
+
packages = Spree::Stock::Coordinator.new(order).packages
|
76
|
+
|
77
|
+
return false if packages.size > order.shipments.size
|
78
|
+
|
79
|
+
variant2quantity = Hash.new(0)
|
80
|
+
|
81
|
+
order.shipments.each do |shipment|
|
82
|
+
shipment.manifest.each do |item|
|
83
|
+
variant2quantity[item.variant.id] += item.quantity
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
return false unless variant2quantity.size == order.line_items.size
|
88
|
+
|
89
|
+
return order.line_items.find_all { |li| variant2quantity[li.variant.id] != li.quantity }.empty?
|
90
|
+
end
|
91
|
+
|
92
|
+
|
87
93
|
end
|
@@ -3,9 +3,6 @@ module Spree
|
|
3
3
|
alias :super_finalize! :finalize!
|
4
4
|
alias :super_after_cancel :after_cancel
|
5
5
|
alias :super_after_resume :after_resume
|
6
|
-
alias :super_update_adjustments :update_adjustments
|
7
|
-
alias :super_update_payment_state :update_payment_state
|
8
|
-
alias :super_update_shipment_state :update_shipment_state
|
9
6
|
|
10
7
|
#check out handler
|
11
8
|
def finalize!
|
@@ -18,7 +15,7 @@ module Spree
|
|
18
15
|
def after_cancel
|
19
16
|
exactor_connector = SpreeExactorConnector::SpreeExactorConnector.new
|
20
17
|
exactor_connector.do_cancel!(self)
|
21
|
-
update_column(:exactor_order_hash_sum,nil)
|
18
|
+
update_column(:exactor_order_hash_sum, nil)
|
22
19
|
super_after_cancel
|
23
20
|
end
|
24
21
|
|
@@ -40,27 +37,18 @@ module Spree
|
|
40
37
|
end
|
41
38
|
end
|
42
39
|
|
40
|
+
#REMARK: this method moved to OrderUpdater class in Spree 2.0.0
|
43
41
|
def update_payment_state
|
44
|
-
|
45
|
-
exactor_connector = SpreeExactorConnector::SpreeExactorConnector.new
|
46
|
-
if (payment_state=='paid')
|
47
|
-
exactor_connector.do_payment_completed!(self)
|
48
|
-
elsif current_payment and current_payment.state == 'void' and current_payment.previous_state == 'completed'
|
49
|
-
exactor_connector.do_refund_payment!(self)
|
50
|
-
end
|
42
|
+
self.updater.update_payment_state
|
51
43
|
end
|
52
44
|
|
45
|
+
#REMARK: this method moved to OrderUpdater class in Spree 2.0.0
|
53
46
|
def update_shipment_state
|
54
|
-
|
55
|
-
if (shipment_state=='shipped')
|
56
|
-
exactor_connector = SpreeExactorConnector::SpreeExactorConnector.new
|
57
|
-
exactor_connector.do_shipp
|
58
|
-
ed!(self)
|
59
|
-
end
|
47
|
+
self.updater.update_shipment_state
|
60
48
|
end
|
61
49
|
|
62
50
|
def create_tax_charge!
|
63
|
-
# destroy any previous adjustments (
|
51
|
+
# destroy any previous adjustments (everything is recalculated from scratch)
|
64
52
|
price_adjustments.each(&:destroy)
|
65
53
|
if (adjustments.tax.reload.size!=1)
|
66
54
|
adjustments.tax.each(&:destroy)
|
@@ -68,50 +56,30 @@ module Spree
|
|
68
56
|
end
|
69
57
|
|
70
58
|
end
|
71
|
-
def is_needed_to_create_adjustment?
|
72
|
-
settings = Spree::ExactorSetting.get_settings
|
73
|
-
if self.completed? and ['complete', 'canceled', 'resumed'].include?(state)
|
74
|
-
if settings and completed_at >= settings.effective_date
|
75
|
-
return true
|
76
|
-
end
|
77
|
-
end
|
78
|
-
return false
|
79
|
-
end
|
80
59
|
|
81
60
|
#this method is intended to add adjustment to old transactions which was created without our plugin
|
61
|
+
#REMARK: this method moved to OrderUpdater class in Spree 2.0.0
|
82
62
|
def update_adjustments
|
83
|
-
|
84
|
-
super_update_adjustments
|
85
|
-
return
|
86
|
-
end
|
87
|
-
count_of_tax_adj = adjustments.reload.tax.size
|
88
|
-
current_tax_adj = adjustments.reload.tax.first
|
89
|
-
unless count_of_tax_adj == 0 or
|
90
|
-
(count_of_tax_adj==1 and !current_tax_adj.originator.nil? and current_tax_adj.originator.is_exactor_default?)
|
91
|
-
adjustments.tax.each(&:destroy)
|
92
|
-
return
|
93
|
-
end
|
94
|
-
if (count_of_tax_adj == 0)
|
95
|
-
TaxRate.match(self).each { |rate| rate.adjust(self) }
|
96
|
-
end
|
97
|
-
super_update_adjustments
|
63
|
+
self.updater.update_adjustments
|
98
64
|
end
|
65
|
+
|
99
66
|
end
|
100
67
|
|
101
68
|
Order.class_eval do
|
102
69
|
attr_accessible :exactor_invoice_transaction, :exactor_commit_transaction, :exactor_order_hash_sum, :exactor_is_edit
|
103
|
-
before_save :on_update
|
104
70
|
after_save :on_saved
|
105
71
|
attr_accessor :current_payment
|
106
72
|
|
107
73
|
#before save
|
108
74
|
def on_update
|
109
|
-
if (adjustments.tax.reload.size==0 and !
|
75
|
+
if (adjustments.tax.reload.size==0 and !shipments.empty?)
|
110
76
|
create_tax_charge!
|
111
77
|
end
|
112
78
|
update_adjustments
|
113
79
|
if ['complete', 'resumed'].include?(state) and !changed_attributes.keys().include?('state')
|
114
|
-
|
80
|
+
# Workaround: in some cases exactor_invoice_transaction exists in cache only.
|
81
|
+
self.exactor_invoice_transaction ||= Spree::Order.find(id).exactor_invoice_transaction
|
82
|
+
if (exactor_commit_transaction.nil? or !exactor_invoice_transaction.nil?) and !exactor_is_edit.nil?
|
115
83
|
edit_order
|
116
84
|
end
|
117
85
|
end
|
@@ -120,6 +88,7 @@ module Spree
|
|
120
88
|
|
121
89
|
#after save
|
122
90
|
def on_saved
|
91
|
+
on_update
|
123
92
|
update_column(:exactor_is_edit, nil);
|
124
93
|
end
|
125
94
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Spree
|
2
|
+
|
3
|
+
OrderUpdater.class_eval do
|
4
|
+
end
|
5
|
+
|
6
|
+
class OrderUpdater
|
7
|
+
alias :super_update_adjustments :update_adjustments
|
8
|
+
alias :super_update_payment_state :update_payment_state
|
9
|
+
alias :super_update_shipment_state :update_shipment_state
|
10
|
+
|
11
|
+
def is_needed_to_create_adjustment?
|
12
|
+
settings = Spree::ExactorSetting.get_settings
|
13
|
+
if order.completed? and ['complete', 'canceled', 'resumed'].include?(order.state)
|
14
|
+
if settings and order.completed_at >= settings.effective_date
|
15
|
+
return true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
|
21
|
+
#this method is intended to add adjustment to old transactions which was created without our plugin
|
22
|
+
def update_adjustments
|
23
|
+
if !is_needed_to_create_adjustment?
|
24
|
+
super_update_adjustments
|
25
|
+
return
|
26
|
+
end
|
27
|
+
count_of_tax_adj = order.adjustments.reload.tax.size
|
28
|
+
current_tax_adj = order.adjustments.reload.tax.first
|
29
|
+
unless count_of_tax_adj == 0 or
|
30
|
+
(count_of_tax_adj==1 and !current_tax_adj.originator.nil? and current_tax_adj.originator.is_exactor_default?)
|
31
|
+
order.adjustments.tax.each(&:destroy)
|
32
|
+
return
|
33
|
+
end
|
34
|
+
if count_of_tax_adj == 0
|
35
|
+
TaxRate.match(order).each { |rate| rate.adjust(order) }
|
36
|
+
end
|
37
|
+
super_update_adjustments
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_payment_state
|
41
|
+
super_update_payment_state
|
42
|
+
exactor_connector = SpreeExactorConnector::SpreeExactorConnector.new
|
43
|
+
# due to unknown reasons payment_state is paid when user add first line item into order
|
44
|
+
# so, we need to check order state too
|
45
|
+
if order.payment_state=='paid' and order.state == :complete
|
46
|
+
exactor_connector.do_payment_completed!(order)
|
47
|
+
elsif order.current_payment and order.current_payment.state == 'void' and order.current_payment.previous_state == 'completed'
|
48
|
+
exactor_connector.do_refund_payment!(order)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def update_shipment_state
|
53
|
+
super_update_shipment_state
|
54
|
+
if (order.shipment_state=='shipped')
|
55
|
+
exactor_connector = SpreeExactorConnector::SpreeExactorConnector.new
|
56
|
+
exactor_connector.do_shipped!(order)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
<%= render :partial => 'spree/admin/shared/configuration_menu' %>
|
2
|
-
|
2
|
+
<% content_for :page_title do %>
|
3
|
+
<%= Spree.t(:exactor_settings) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<div>
|
3
7
|
<span style="float:right;display: inline;
|
4
8
|
color: #666;
|
5
9
|
margin-top: 10px;
|
6
|
-
font-size: 8pt;">Exactor Plug-in Version: <%= SpreeExactorConnector::SpreeExactorConnector::PLUGIN_VERSION %></span
|
10
|
+
font-size: 8pt;">Exactor Plug-in Version: <%= SpreeExactorConnector::SpreeExactorConnector::PLUGIN_VERSION %></span>
|
11
|
+
<div class="clear"> </div>
|
12
|
+
</div>
|
7
13
|
<%= render :partial => 'spree/shared/error_messages', :locals => { :target => @setting } %>
|
8
14
|
<% action = @setting.id.nil? ? "create":"update" %>
|
9
15
|
<%= form_for @setting, :url => { :action => action , :id =>@setting.id } do |f| %>
|
data/config/locales/en.yml
CHANGED
@@ -9,6 +9,7 @@ module SpreeExactor
|
|
9
9
|
|
10
10
|
def install
|
11
11
|
supported_versions '1.1.1.112920126'=>['1.1.1','1.1.2','1.1.3']
|
12
|
+
supported_versions '1.1.2.20130723'=>['2.0.*']
|
12
13
|
unless @supported_versions.include? _plugin_version
|
13
14
|
puts "Unknown plug-in version. Try any of those: "+ @supported_versions.keys.to_s
|
14
15
|
exit(0)
|
data/spree_exactor.gemspec
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.platform = Gem::Platform::RUBY
|
4
4
|
s.name = 'spree_exactor'
|
5
|
-
s.version = '1.1.
|
5
|
+
s.version = '1.1.2.20130723'
|
6
6
|
s.summary = 'Exactor sales tax compliance module for SpreeCommerce'
|
7
7
|
s.description = 'Sales tax compliance module for (i) calculating sales tax with SpreeCommerce; and (ii) generating and filing sales tax returns in all US jurisdictions (state and local).'
|
8
|
-
s.required_ruby_version = '>=
|
8
|
+
s.required_ruby_version = '>= 2.0.0'
|
9
9
|
|
10
10
|
s.author = 'Exactor, Inc'
|
11
11
|
s.email = 'spreecommerce@exactor.com'
|
@@ -44,6 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
"app/models/spree/tax_category_decorator.rb",
|
45
45
|
"app/models/spree/line_item_decorator.rb",
|
46
46
|
"app/models/spree/order_decorator.rb",
|
47
|
+
"app/models/spree/order_updater_decorator.rb",
|
47
48
|
"app/models/spree/tax_rate_decorator.rb",
|
48
49
|
"app/models/spree/adjustment_decorator.rb",
|
49
50
|
"app/models/spree/payment_decorator.rb",
|
@@ -55,12 +56,8 @@ Gem::Specification.new do |s|
|
|
55
56
|
s.require_path = 'lib'
|
56
57
|
s.requirements << 'none'
|
57
58
|
|
58
|
-
s.add_dependency 'spree_core', '>=
|
59
|
+
s.add_dependency 'spree_core', '>= 2.0.0'
|
59
60
|
s.add_dependency 'xml-simple'
|
60
|
-
|
61
|
-
s.
|
62
|
-
s.add_development_dependency 'factory_girl', '~> 2.6.4'
|
63
|
-
s.add_development_dependency 'ffaker'
|
64
|
-
s.add_development_dependency 'rspec-rails', '~> 2.9'
|
65
|
-
s.add_development_dependency 'sqlite3'
|
61
|
+
s.add_dependency 'rspec'
|
62
|
+
s.add_dependency 'sqlite3'
|
66
63
|
end
|
metadata
CHANGED
@@ -1,126 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_exactor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.2.20130723
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Exactor, Inc
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-07-23 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: spree_core
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
19
|
+
version: 2.0.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
26
|
+
version: 2.0.0
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: xml-simple
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
42
|
+
name: rspec
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- - '
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 1.0.1
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - '='
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 1.0.1
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: factory_girl
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: 2.6.4
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 2.6.4
|
78
|
-
- !ruby/object:Gem::Dependency
|
79
|
-
name: ffaker
|
80
|
-
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
|
-
requirements:
|
83
|
-
- - ! '>='
|
45
|
+
- - '>='
|
84
46
|
- !ruby/object:Gem::Version
|
85
47
|
version: '0'
|
86
|
-
type: :
|
48
|
+
type: :runtime
|
87
49
|
prerelease: false
|
88
50
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
51
|
requirements:
|
91
|
-
- -
|
52
|
+
- - '>='
|
92
53
|
- !ruby/object:Gem::Version
|
93
54
|
version: '0'
|
94
|
-
- !ruby/object:Gem::Dependency
|
95
|
-
name: rspec-rails
|
96
|
-
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
|
-
requirements:
|
99
|
-
- - ~>
|
100
|
-
- !ruby/object:Gem::Version
|
101
|
-
version: '2.9'
|
102
|
-
type: :development
|
103
|
-
prerelease: false
|
104
|
-
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ~>
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
version: '2.9'
|
110
55
|
- !ruby/object:Gem::Dependency
|
111
56
|
name: sqlite3
|
112
57
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
58
|
requirements:
|
115
|
-
- -
|
59
|
+
- - '>='
|
116
60
|
- !ruby/object:Gem::Version
|
117
61
|
version: '0'
|
118
|
-
type: :
|
62
|
+
type: :runtime
|
119
63
|
prerelease: false
|
120
64
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
65
|
requirements:
|
123
|
-
- -
|
66
|
+
- - '>='
|
124
67
|
- !ruby/object:Gem::Version
|
125
68
|
version: '0'
|
126
69
|
description: Sales tax compliance module for (i) calculating sales tax with SpreeCommerce;
|
@@ -163,6 +106,7 @@ files:
|
|
163
106
|
- app/models/spree/tax_category_decorator.rb
|
164
107
|
- app/models/spree/line_item_decorator.rb
|
165
108
|
- app/models/spree/order_decorator.rb
|
109
|
+
- app/models/spree/order_updater_decorator.rb
|
166
110
|
- app/models/spree/tax_rate_decorator.rb
|
167
111
|
- app/models/spree/adjustment_decorator.rb
|
168
112
|
- app/models/spree/payment_decorator.rb
|
@@ -171,27 +115,26 @@ files:
|
|
171
115
|
- app/models/spree/user_decorator.rb
|
172
116
|
homepage: http://exactor.com
|
173
117
|
licenses: []
|
118
|
+
metadata: {}
|
174
119
|
post_install_message:
|
175
120
|
rdoc_options: []
|
176
121
|
require_paths:
|
177
122
|
- lib
|
178
123
|
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
-
none: false
|
180
124
|
requirements:
|
181
|
-
- -
|
125
|
+
- - '>='
|
182
126
|
- !ruby/object:Gem::Version
|
183
|
-
version:
|
127
|
+
version: 2.0.0
|
184
128
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
|
-
none: false
|
186
129
|
requirements:
|
187
|
-
- -
|
130
|
+
- - '>='
|
188
131
|
- !ruby/object:Gem::Version
|
189
132
|
version: '0'
|
190
133
|
requirements:
|
191
134
|
- none
|
192
135
|
rubyforge_project:
|
193
|
-
rubygems_version:
|
136
|
+
rubygems_version: 2.0.3
|
194
137
|
signing_key:
|
195
|
-
specification_version:
|
138
|
+
specification_version: 4
|
196
139
|
summary: Exactor sales tax compliance module for SpreeCommerce
|
197
140
|
test_files: []
|