spree_exactor 1.1.1.112920126 → 1.1.2.20130723
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|