spree_order_groove 3.0.0

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.
Files changed (39) hide show
  1. data/.gitignore +14 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +7 -0
  4. data/LICENSE +26 -0
  5. data/README.md +60 -0
  6. data/Rakefile +21 -0
  7. data/app/assets/javascripts/spree/backend/spree_order_groove.js +2 -0
  8. data/app/assets/javascripts/spree/frontend/spree_order_groove.js +2 -0
  9. data/app/assets/stylesheets/spree/backend/spree_order_groove.css +4 -0
  10. data/app/assets/stylesheets/spree/frontend/spree_order_groove.css +4 -0
  11. data/app/controllers/spree/api/orders_controller_decorator.rb +293 -0
  12. data/app/controllers/spree/checkout_controller_decorator.rb +102 -0
  13. data/app/controllers/spree/orders_controller_decorator.rb +4 -0
  14. data/app/controllers/spree/store_controller_decorator.rb +24 -0
  15. data/app/models/spree/ordergroove_configuration.rb +12 -0
  16. data/app/models/spree/promotion/rules/autodelivery.rb +23 -0
  17. data/app/overrides/decorate_ordergroove_div_cart.rb +6 -0
  18. data/app/overrides/decorate_ordergroove_div_cart_remove.rb +6 -0
  19. data/app/overrides/decorate_ordergroove_div_product_main.rb +6 -0
  20. data/app/overrides/decorate_ordergroove_tags_cart.rb +6 -0
  21. data/app/overrides/decorate_ordergroove_tags_product.rb +6 -0
  22. data/app/views/spree/admin/promotions/rules/_autodelivery_rule.html.erb +0 -0
  23. data/app/views/spree/api/orders/ogcreateorder.v1.rabl +2 -0
  24. data/app/views/spree/shared/_ordergroove_line_item_div.html.erb +4 -0
  25. data/app/views/spree/shared/_ordergroove_line_item_div_remove.html.erb +3 -0
  26. data/app/views/spree/shared/_ordergroove_tags.html.erb +56 -0
  27. data/bin/rails +7 -0
  28. data/config/locales/en.yml +10 -0
  29. data/config/ordergroove.yml +35 -0
  30. data/config/routes.rb +10 -0
  31. data/db/migrate/20150604115532_add_auto_delivery_to_spree_line_items.spree_order_groove.rb +5 -0
  32. data/lib/generators/spree_order_groove/install/install_generator.rb +31 -0
  33. data/lib/rc4.rb +64 -0
  34. data/lib/spree_order_groove.rb +2 -0
  35. data/lib/spree_order_groove/engine.rb +23 -0
  36. data/lib/spree_order_groove/factories.rb +6 -0
  37. data/spec/spec_helper.rb +87 -0
  38. data/spree_order_groove.gemspec +31 -0
  39. metadata +268 -0
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ .sass-cache
8
+ coverage
9
+ Gemfile.lock
10
+ tmp
11
+ nbproject
12
+ pkg
13
+ *.swp
14
+ spec/dummy
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'spree', github: 'spree/spree', branch: '3-0-stable'
4
+ # Provides basic authentication functionality for testing parts of your engine
5
+ gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '3-0-stable'
6
+
7
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2015 [name of plugin creator]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ SpreeOrderGroove
2
+ ================
3
+
4
+ Order Groove provide the retain engine for ecommerce web sites, all customer sign up for auto delivery. This spree extension integrate it into spree.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ This extension integrate the classical OrderGroove server. It tags products page, checkout pages, create credit, and provide the drop order API to orderGroove.
10
+
11
+ you need one orderGroove account to test it.
12
+
13
+ This extension assume you are using multi-domain extension or the spree 3.0 which support multi-domain.
14
+ The API call you give to OrderGroove will be:
15
+ yourdomain.com/api/orders/ogcreateorder
16
+
17
+ one example call in linux is:
18
+ curl -X POST -H "Content-Type: text/xml" -d "@the_order_from_ordergroove.xml" --header "X-Spree-Token: the_token_you_authorize_ordergroove" yourdomain.com/api/orders/ogcreateorder
19
+
20
+ Setup in Spree
21
+ ------------
22
+ Create new production, add the rule of Order Groove Auto delivery discount
23
+ you can add other rules to limit it
24
+ Add action for Percent Per Item, and set the percent you want.
25
+
26
+ ```ruby
27
+ gem 'spree_order_groove'
28
+ ```
29
+
30
+ Bundle your dependencies and run the installation generator:
31
+
32
+ ```shell
33
+ bundle
34
+ bundle exec rails g spree_order_groove:install
35
+ ```
36
+
37
+ Testing
38
+ -------
39
+
40
+ First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`.
41
+
42
+ ```shell
43
+ bundle
44
+ bundle exec rake
45
+ ```
46
+
47
+ When testing your applications integration with this extension you may use it's factories.
48
+ Simply add this require statement to your spec_helper:
49
+
50
+ ```ruby
51
+ require 'spree_order_groove/factories'
52
+ ```
53
+
54
+ register the promotion using this code inside config/initializers/spree.rb:
55
+ Rails.application.config.spree.promotions.rules << Spree::Promotion::Rules::Autodelivery
56
+
57
+ Contact me at albertliu at naturalwellbeing dot com.
58
+
59
+
60
+ Copyright (c) 2015 Naturalwellbeing.com, released under the New BSD License
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir["spec/dummy"].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir("../../")
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'spree_order_groove'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,293 @@
1
+ Spree::Api::OrdersController.class_eval do
2
+
3
+ skip_before_action :authenticate_user, only: :ogcreateorder
4
+ skip_before_action :find_order, only: :ogcreateorder
5
+
6
+ def ogcreateorder
7
+
8
+ #****************************
9
+ # linux shell call to this api
10
+ # curl -X POST -H "Content-Type: text/xml" -d "@og_test1.xml" --header "X-Spree-Token: your_customers_user_key" local.naturalwellbeing.com:8080/api/orders/ogcreateorder
11
+ # assume og_test1.xml should be in you current folder here. X-Spree-Token is from spree_users
12
+
13
+ #****************************
14
+
15
+ og_logger ||= Logger.new("#{Rails.root}/log/og.log")
16
+ # 0. get the RC4 Hash key
17
+ merchant_id= Spree::OrdergrooveConfiguration.account["#{current_store.code}"]["og_merchant_id"]
18
+ hashkey= Spree::OrdergrooveConfiguration.account["#{current_store.code}"]["og_hashkey"]
19
+ rc4=RC4.new(hashkey)
20
+ #begin
21
+ # 1. parse xml (rails active support)
22
+ #render :text => 'xml for orderOgId is: ' + params['order']['head']['orderOgId']
23
+
24
+ # 2. check all parameters there
25
+ # rails4 seems not recognizing xml as params
26
+ string = request.body.read
27
+ params = Hash.from_xml(string)
28
+
29
+ errstr='parameter in OG xml is not complete'
30
+
31
+ og_logger.info("#{Time.zone.at(Time.new()).strftime("%B %d, %Y at %I:%M PST")} :\n Start processing og dropped order: #{params.to_xml}") # this xml is the re-generated one
32
+ og_logger.info "#params.inspect"
33
+
34
+ # 2.5 validate xml data ingrety
35
+ strxml_error=''
36
+ if params['order']['customer']['customerFirstName'].blank?
37
+ strxml_error += 'customer first name blank,'
38
+ end
39
+ if params['order']['customer']['customerLastName'].blank?
40
+ strxml_error += 'customer last name blank,'
41
+ end
42
+ if params['order']['customer']['customerShippingAddress1'].blank?
43
+ strxml_error += 'customer shipping address blank,'
44
+ end
45
+ if params['order']['customer']['customerShippingCity'].blank?
46
+ strxml_error += 'customer shipping city blank,'
47
+ end
48
+ if params['order']['customer']['customerShippingState'].blank?
49
+ strxml_error += 'customer shipping state blank,'
50
+ end
51
+ if params['order']['customer']['customerShippingCountry'].blank?
52
+ strxml_error += 'customer shipping country blank,'
53
+ end
54
+ if params['order']['customer']['customerShippingZip'].blank?
55
+ strxml_error += 'customer shipping zip code blank,'
56
+ end
57
+ if params['order']['customer']['customerShippingPhone'].blank?
58
+ strxml_error += 'customer shipping phone blank,'
59
+ end
60
+
61
+ if params['order']['customer']['customerBillingAddress1'].blank?
62
+ strxml_error += 'customer Billing address blank,'
63
+ end
64
+ if params['order']['customer']['customerBillingCity'].blank?
65
+ strxml_error += 'customer Billing city blank,'
66
+ end
67
+ if params['order']['customer']['customerBillingState'].blank?
68
+ strxml_error += 'customer Billing state blank,'
69
+ end
70
+ if params['order']['customer']['customerBillingCountry'].blank?
71
+ strxml_error += 'customer Billing country blank,'
72
+ end
73
+ if params['order']['customer']['customerBillingZip'].blank?
74
+ strxml_error += 'customer Billing zip code blank,'
75
+ end
76
+ if params['order']['customer']['customerBillingPhone'].blank?
77
+ strxml_error += 'customer Billing phone blank,'
78
+ end
79
+ if params['order']['customer']['customerPartnerId'].blank? && params['order']['customer']['customerEmail'].blank?
80
+ strxml_error += 'customer customerEmail or customerPartnerId can not be both blank,'
81
+ end
82
+ if strxml_error.length>0
83
+ render :xml =>'<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>130</errorCode><errorMsg>' + strxml_error + '</errorMsg></order>'
84
+ else
85
+
86
+
87
+
88
+ # 3. create order
89
+ if params['order']['customer']['customerPartnerId'].blank?
90
+ user=Spree::User.find_by_email(params['order']['customer']['customerEmail'])
91
+ else
92
+ user=Spree::User.find(params['order']['customer']['customerPartnerId'])
93
+ end
94
+ if !user
95
+ render :xml =>'<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>130</errorCode><errorMsg>User does not exist</errorMsg></order>'
96
+ else
97
+
98
+ order=user.orders.create(:store_id=>current_store.id, :item_total=>params['order']['head']['orderSubtotalValue'])
99
+
100
+ #order.update_attribute(:user_id, user) unless !user
101
+
102
+ ship_address=Spree::Address.create(:firstname=>params['order']['customer']['customerFirstName'],
103
+ :lastname=>params['order']['customer']['customerLastName'],
104
+ :address1=>params['order']['customer']['customerShippingAddress1'],
105
+ :address2=>params['order']['customer']['customerShippingAddress2'],
106
+ :city=>params['order']['customer']['customerShippingCity'],
107
+ :state_id=>Spree::State.find_by_abbr(params['order']['customer']['customerShippingState']).id.to_s|| '',
108
+ :country_id=>Spree::Country.find_by_iso(params['order']['customer']['customerShippingCountry']).id.to_s||'',
109
+ :zipcode=>params['order']['customer']['customerShippingZip'],
110
+ :phone=>params['order']['customer']['customerShippingPhone']
111
+ )
112
+ ship_address.save!
113
+
114
+ bill_address=Spree::Address.create(:firstname=>params['order']['customer']['customerFirstName'],
115
+ :lastname=>params['order']['customer']['customerLastName'],
116
+ :address1=>params['order']['customer']['customerBillingAddress1'],
117
+ :address2=>params['order']['customer']['customerBillingAddress2'],
118
+ :city=>params['order']['customer']['customerBillingCity'],
119
+ :state_id=>Spree::State.find_by_abbr(params['order']['customer']['customerBillingState']).id.to_s|| '',
120
+ :country_id=>Spree::Country.find_by_iso(params['order']['customer']['customerBillingCountry']).id.to_s||'',
121
+ :zipcode=>params['order']['customer']['customerBillingZip'],
122
+ :phone=>params['order']['customer']['customerBillingPhone']
123
+ )
124
+ bill_address.save!
125
+ if params['order']['customer']['customerShippingCountry']=="CA"
126
+ shipping_method=Spree::ShippingMethod.find_by_code('USP1')
127
+ else
128
+ if ['HI','AK'].include? params['order']['customer']['customerShippingState'] #hi, ak use usps
129
+ shipping_method=Spree::ShippingMethod.find_by_code('M03')||Spree::ShippingMethod.find_by_zone_id_and_code(2,'U11R')
130
+ else
131
+ shipping_method=Spree::ShippingMethod.find_by_code('SUR')||Spree::Zone.find(2).shipping_methods.select{|s|s.code=='FSP'}
132
+ end
133
+ end
134
+ order.update_attributes(:email=>params['order']['customer']['customerEmail'], :ship_address_id=>ship_address.id, :bill_address_id=>bill_address.id, :shipping_method_id => shipping_method.id)
135
+
136
+
137
+
138
+ order.shipments.each do |shipment|
139
+ shipment.update_attributes(:address_id=>ship_address.id,:cost=>params['order']['head']['orderShipping'].to_f)
140
+ end
141
+
142
+
143
+ og_discount=[]
144
+ if params['order']['items']['item'].class == Array
145
+ items=params['order']['items']['item']
146
+ else
147
+ items=[params['order']['items']['item']]
148
+ end
149
+
150
+
151
+
152
+ items.each do |item|
153
+
154
+ #byebug
155
+ variant=Spree::Variant.find(item['product_id'].to_i)
156
+ line_item=order.contents.add(
157
+ variant,
158
+ item['qty'].to_i || 1,
159
+ {auto_delivery: true, price: item['price']}
160
+ )
161
+ Spree::Adjustment.create(:order_id=>order.id, :amount=>item['discount'].to_f*(-1),:label =>'Auto Delivery Discount', :source_type => "Spree::PromotionAction", :adjustable_id => line_item.id, :adjustable_type => "Spree::LineItem") # discount
162
+
163
+
164
+ end
165
+ order.create_proposed_shipments
166
+
167
+ order.line_items.each do |line_item|
168
+ variant=Spree::Variant.find(line_item['variant_id'])
169
+ if (variant.respond_to? :assembly) && variant.assembly?
170
+ variant.parts.each do|v|
171
+ line_item['quantity'].to_i.times {
172
+ v.count.to_i.times {
173
+ order.inventory_units.create(:variant_id=>v.id,:state=>'sold', :shipment_id=>order.shipments.first.id, :line_item_id=>line_item.id)
174
+ }
175
+ }
176
+ end
177
+ else
178
+ line_item['quantity'].to_i.times {
179
+ order.inventory_units.create(:variant_id=>variant.id,:state=>'sold', :shipment_id=>order.shipments.first.id, :line_item_id=>line_item.id)
180
+ }
181
+ end
182
+ end
183
+
184
+
185
+
186
+ order.reload
187
+ #order.update_totals
188
+ order.total = params['order']['head']['orderTotalValue'].to_f
189
+ #order.item_total = params['order']['head']['orderSubtotalValue'].to_f
190
+
191
+ order.line_items.each do |l|
192
+ l.auto_delivery= true
193
+ end
194
+
195
+ #order.save!
196
+ #order.adjustments.first.destroy
197
+
198
+ #order.adjustments.select{|a| a.source_type=="Spree::TaxRate"}.first.amount=params['order']['head']['orderSalesTax'].to_f
199
+ #order.adjustments.select{|a| a.source_type=="Spree::TaxRate"}.first.save!
200
+ Spree::Adjustment.create(:order_id=>order.id, :amount=>params['order']['head']['orderSalesTax'].to_f, :label =>'Tax', :source_type => "Spree::TaxRate", :adjustable_id => order.id, :adjustable_type => "Spree::Order")
201
+
202
+
203
+ #shippings=order.adjustments.select{|a| a.source_type=="Spree::ShippingCharge"}
204
+
205
+ if params['order']['head']['orderShipping'].to_f == 0.00
206
+ # order.adjustments.select{|a| a.type=="ShippingCharge"}.first.destroy
207
+ end
208
+ #order.line_items.each do |line_item|
209
+ #Spree::Adjustment.create(:order_id=>order.id, :amount=>4.5*(-1),:label =>'Auto Delivery Discount', :source_type => "Spree::PromotionAction", :adjustable_id => line_item.id, :adjustable_type => "Spree::LineItem") # discount
210
+ #end
211
+
212
+ order.save!
213
+ # to overwrite the possilbe tax update to 0, reset the total
214
+ order.total = params['order']['head']['orderTotalValue'].to_f
215
+
216
+ # 4. payment
217
+ if params['order']['head']['orderPaymentMethod']== 'CC'
218
+ payment_method=Spree::PaymentMethod.where(:name=>'Credit Card').first
219
+
220
+ payment=Spree::Payment.create(:order_id=>order.id,
221
+ :amount=>order.total,
222
+ :payment_method_id=>payment_method.id
223
+ )
224
+
225
+ expire_date=rc4.decrypt(Base64.decode64(params['order']['head']['orderCcExpire'])).split('/')
226
+ payment.source = payment_method.payment_source_class.new(:number=>rc4.decrypt(Base64.decode64(params['order']['head']['orderCcNumber'])),
227
+ :month=>expire_date[0].to_i.to_s,
228
+ :year=>expire_date[1],
229
+ :verification_value=>213, #params['order']['head']['orderCcNumber'],
230
+ :name=>params['order']['customer']['customerBillingFirstName'] +' '+params['order']['customer']['customerBillingLastName']
231
+ )
232
+
233
+ begin
234
+ payment.source.number=rc4.decrypt(Base64.decode64(params['order']['head']['orderCcNumber']))
235
+ payment_method.create_profile(payment)
236
+ order.total=order.item_total+ order.adjustments.map(&:amount).inject(:+)
237
+
238
+ payment.started_processing!
239
+ payment.pend!
240
+
241
+ order.update_attributes({:state => "complete", :completed_at => Time.now})
242
+ #order.update_attribute(:automated_approved_at, Time.now)
243
+ until order.state == "complete"
244
+ if order.next!
245
+ order.update!
246
+ state_callback(:after)
247
+ end
248
+ end
249
+ order.finalize!
250
+ og_logger.info("og order is successfully created in nwb with number: #{order.number}")
251
+ result_xml='<?xml version="1.0" encoding="UTF-8"?><order><code>SUCCESS</code><orderId>' + order.number + '</orderId><errorMsg /></order>'
252
+ rescue Spree::Core::GatewayError => ge
253
+ # if it fails, destroy the payment and clear the autodelivery discount and flag
254
+ payment.destroy
255
+ order.destroy
256
+ ge=ge.to_s
257
+ error_code='140' #ge.params.messages.message.result_code
258
+ if ge.include? ',,,,,,,,' #this is raw of direct_response
259
+
260
+ response_error_code=ge.split(',')[2]
261
+ if %w(17).include? response_error_code
262
+ error_code='100'
263
+ elsif %w(6,28,37,78).include? response_error_code
264
+ error_code='110'
265
+ elsif %w(7,8).include? response_error_code
266
+ error_code='120'
267
+ elsif %w(27,127).include? response_error_code
268
+ error_code='130'
269
+ end
270
+ error_message = ge.params['message'] || ge.params['response_reason_text'] || ge.message
271
+ else
272
+ error_message=ge #'' #ge.params.messages.message.text
273
+ end
274
+
275
+ og_logger.info("error happened in making the payment with creditcard: #{ge}")
276
+ result_xml='<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>' + error_code + '</errorCode><errorMsg>' + error_message + '</errorMsg></order>'
277
+ end
278
+ else
279
+ errstr="The payment method should be CC"
280
+ og_logger.info("error happened in processing og order: #{errstr}")
281
+ result_xml='<?xml version="1.0" encoding="UTF-8"?><order><code>ERROR</code><errorCode>999</errorCode><errorMsg>' + errstr + '</errorMsg></order>'
282
+
283
+ #raise(errstr)
284
+ end
285
+
286
+ # 5. response xml with code and message
287
+ render :xml => result_xml #order.to_xml
288
+ end
289
+ end
290
+
291
+ end
292
+
293
+ end