effective_orders 1.8.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +150 -60
  4. data/Rakefile +0 -3
  5. data/active_admin/effective_orders.rb +14 -9
  6. data/app/assets/javascripts/effective_orders.js +2 -0
  7. data/app/assets/javascripts/effective_orders/{stripe_charges.js.coffee → providers/stripe_charges.js.coffee} +1 -1
  8. data/app/assets/javascripts/effective_orders/{stripe_subscriptions.js.coffee → providers/stripe_subscriptions.js.coffee} +1 -1
  9. data/app/assets/stylesheets/effective_orders/_order.scss +9 -3
  10. data/app/controllers/admin/orders_controller.rb +87 -3
  11. data/app/controllers/concerns/acts_as_active_admin_controller.rb +2 -1
  12. data/app/controllers/effective/carts_controller.rb +4 -2
  13. data/app/controllers/effective/orders_controller.rb +101 -60
  14. data/app/controllers/effective/providers/app_checkout.rb +10 -2
  15. data/app/controllers/effective/providers/ccbill.rb +34 -0
  16. data/app/controllers/effective/providers/cheque.rb +30 -0
  17. data/app/controllers/effective/providers/moneris.rb +7 -7
  18. data/app/controllers/effective/providers/paypal.rb +7 -5
  19. data/app/controllers/effective/providers/pretend.rb +22 -0
  20. data/app/controllers/effective/providers/stripe.rb +26 -24
  21. data/app/controllers/effective/webhooks_controller.rb +1 -1
  22. data/app/helpers/effective_carts_helper.rb +59 -29
  23. data/app/helpers/effective_ccbill_helper.rb +25 -0
  24. data/app/helpers/effective_orders_helper.rb +50 -41
  25. data/app/helpers/effective_paypal_helper.rb +11 -11
  26. data/app/mailers/effective/orders_mailer.rb +95 -20
  27. data/app/models/concerns/acts_as_purchasable.rb +14 -22
  28. data/app/models/effective/cart.rb +9 -15
  29. data/app/models/effective/cart_item.rb +15 -13
  30. data/app/models/effective/customer.rb +9 -9
  31. data/app/models/effective/datatables/order_items.rb +14 -8
  32. data/app/models/effective/datatables/orders.rb +56 -69
  33. data/app/models/effective/order.rb +250 -139
  34. data/app/models/effective/order_item.rb +23 -16
  35. data/app/models/effective/product.rb +23 -0
  36. data/app/models/effective/providers/ccbill_postback.rb +85 -0
  37. data/app/models/effective/{stripe_charge.rb → providers/stripe_charge.rb} +1 -1
  38. data/app/models/effective/subscription.rb +16 -12
  39. data/app/models/effective/tax_rate_calculator.rb +45 -0
  40. data/app/views/admin/customers/index.html.haml +2 -5
  41. data/app/views/admin/order_items/index.html.haml +2 -5
  42. data/app/views/admin/orders/_actions.html.haml +2 -0
  43. data/app/views/admin/orders/_form.html.haml +28 -0
  44. data/app/views/admin/orders/_order_item_fields.html.haml +9 -0
  45. data/app/views/admin/orders/index.html.haml +9 -5
  46. data/app/views/admin/orders/new.html.haml +3 -0
  47. data/app/views/effective/carts/_cart.html.haml +3 -12
  48. data/app/views/effective/carts/_cart_actions.html.haml +4 -0
  49. data/app/views/effective/carts/show.html.haml +10 -12
  50. data/app/views/effective/orders/_checkout_step1.html.haml +46 -0
  51. data/app/views/effective/orders/_checkout_step2.html.haml +33 -0
  52. data/app/views/effective/orders/_order.html.haml +2 -0
  53. data/app/views/effective/orders/_order_actions.html.haml +10 -5
  54. data/app/views/effective/orders/_order_footer.html.haml +1 -0
  55. data/app/views/effective/orders/_order_items.html.haml +11 -9
  56. data/app/views/effective/orders/_order_note.html.haml +8 -0
  57. data/app/views/effective/orders/_order_note_fields.html.haml +5 -0
  58. data/app/views/effective/orders/_order_shipping.html.haml +4 -4
  59. data/app/views/effective/orders/_order_user_fields.html.haml +1 -0
  60. data/app/views/effective/orders/_orders_table.html.haml +27 -0
  61. data/app/views/effective/orders/ccbill/_form.html.haml +24 -0
  62. data/app/views/effective/orders/checkout_step1.html.haml +3 -0
  63. data/app/views/effective/orders/checkout_step2.html.haml +3 -0
  64. data/app/views/effective/orders/cheque/_form.html.haml +2 -0
  65. data/app/views/effective/orders/cheque/pay_by_cheque.html.haml +9 -0
  66. data/app/views/effective/orders/declined.html.haml +4 -2
  67. data/app/views/effective/orders/my_purchases.html.haml +1 -1
  68. data/app/views/effective/orders/my_sales.html.haml +1 -1
  69. data/app/views/effective/orders/purchased.html.haml +3 -2
  70. data/app/views/effective/orders/show.html.haml +1 -1
  71. data/app/views/effective/orders/stripe/_form.html.haml +5 -5
  72. data/app/views/effective/orders_mailer/order_error.html.haml +11 -0
  73. data/app/views/effective/orders_mailer/payment_request_to_buyer.html.haml +13 -0
  74. data/app/views/effective/orders_mailer/pending_order_invoice_to_buyer.html.haml +13 -0
  75. data/app/views/layouts/effective_orders_mailer_layout.html.haml +7 -7
  76. data/config/routes.rb +39 -24
  77. data/db/migrate/01_create_effective_orders.rb.erb +20 -1
  78. data/db/upgrade/03_upgrade_effective_orders_from1x.rb.erb +95 -0
  79. data/lib/effective_orders.rb +67 -9
  80. data/lib/effective_orders/app_checkout_service.rb +1 -2
  81. data/lib/effective_orders/engine.rb +46 -14
  82. data/lib/effective_orders/version.rb +1 -1
  83. data/lib/generators/effective_orders/install_generator.rb +1 -0
  84. data/lib/generators/effective_orders/upgrade_from03x_generator.rb +1 -0
  85. data/lib/generators/effective_orders/upgrade_from1x_generator.rb +31 -0
  86. data/lib/generators/templates/effective_orders.rb +131 -66
  87. data/lib/generators/templates/effective_orders_mailer_preview.rb +28 -13
  88. data/spec/controllers/admin/orders_controller_spec.rb +242 -0
  89. data/spec/controllers/ccbill_orders_controller_spec.rb +103 -0
  90. data/spec/controllers/moneris_orders_controller_spec.rb +23 -23
  91. data/spec/controllers/orders_controller_spec.rb +167 -79
  92. data/spec/controllers/stripe_orders_controller_spec.rb +7 -7
  93. data/spec/dummy/app/models/product.rb +0 -8
  94. data/spec/dummy/app/models/product_with_float_price.rb +0 -8
  95. data/spec/dummy/app/models/user.rb +2 -19
  96. data/spec/dummy/config/application.rb +2 -1
  97. data/spec/dummy/config/environments/test.rb +1 -0
  98. data/spec/dummy/config/initializers/effective_orders.rb +109 -64
  99. data/spec/dummy/db/schema.rb +15 -2
  100. data/spec/dummy/db/test.sqlite3 +0 -0
  101. data/spec/dummy/log/test.log +0 -258
  102. data/spec/models/acts_as_purchasable_spec.rb +8 -6
  103. data/spec/models/factories_spec.rb +7 -1
  104. data/spec/models/order_item_spec.rb +1 -1
  105. data/spec/models/order_spec.rb +165 -46
  106. data/spec/models/stripe_charge_spec.rb +5 -5
  107. data/spec/spec_helper.rb +2 -0
  108. data/spec/support/factories.rb +49 -33
  109. metadata +47 -64
  110. data/app/views/effective/orders/_checkout_step_1.html.haml +0 -43
  111. data/app/views/effective/orders/_checkout_step_2.html.haml +0 -25
  112. data/app/views/effective/orders/_my_purchases.html.haml +0 -17
  113. data/app/views/effective/orders/checkout.html.haml +0 -3
  114. data/app/views/effective/orders/new.html.haml +0 -4
  115. data/spec/dummy/log/development.log +0 -82
@@ -8,6 +8,8 @@ EffectiveOrders.setup do |config|
8
8
  config.cart_items_table_name = :cart_items
9
9
  config.customers_table_name = :customers
10
10
  config.subscriptions_table_name = :subscriptions
11
+ config.products_table_name = :products
12
+
11
13
 
12
14
  # Authorization Method
13
15
  #
@@ -30,6 +32,12 @@ EffectiveOrders.setup do |config|
30
32
  # config.authorization_method = false
31
33
  config.authorization_method = Proc.new { |controller, action, resource| true }
32
34
 
35
+ # Skip automatically mounting the EffectiveOrders engine
36
+ config.skip_mount_engine = false
37
+
38
+ # Filter the @orders on admin/orders#index screen
39
+ # config.orders_collection_scope = Proc.new { |scope| scope.where(...) }
40
+
33
41
  # Register Effective::Order with ActiveAdmin if ActiveAdmin is present
34
42
  # You must have authorization to authorized?(:manage, Effective::Order)
35
43
  # For the activeadmin menu to item to show up
@@ -50,7 +58,7 @@ EffectiveOrders.setup do |config|
50
58
  # Works with effective_addresses gem
51
59
  config.use_address_full_name = true
52
60
 
53
- # If set, the orders#new screen will render effective/orders/user_fields partial and capture this User Info
61
+ # If set, the orders#new screen will render effective/orders/_order_user_fields to capture this User Info
54
62
  # The partial can be overridden to customize the form, but the following fields are also fed into strong_paramters
55
63
  config.collect_user_fields = []
56
64
  #config.collect_user_fields = [:salutation, :first_name, :last_name] # Must be valid fields on the User object
@@ -58,8 +66,13 @@ EffectiveOrders.setup do |config|
58
66
  # Don't validate_associated :user when saving an Order
59
67
  config.skip_user_validation = false
60
68
 
69
+ # If set, the orders#new screen will render effective/orders/_order_note_fields to capture any Note info
70
+ config.collect_note = false
71
+ config.collect_note_required = false # just required for the form, not a true Order model validation
72
+ config.collect_note_message = ''
73
+
61
74
  # Tax Calculation Method
62
- config.tax_rate_method = Proc.new { |acts_as_purchasable| 0.05 } # Regardless of the object, charge 5% tax (GST)
75
+ config.order_tax_rate_method = Proc.new { |order| Effective::TaxRateCalculator.new(order: order).tax_rate }
63
76
 
64
77
  # Minimum Charge
65
78
  # Prevent orders less than this value from being purchased
@@ -99,24 +112,25 @@ EffectiveOrders.setup do |config|
99
112
 
100
113
  # config.layout = 'application' # All EffectiveOrders controllers will use this layout
101
114
  config.layout = {
102
- :carts => 'application',
103
- :orders => 'application',
104
- :subscriptions => 'application',
105
- :admin_customers => 'application',
106
- :admin_orders => 'application'
115
+ carts: 'application',
116
+ orders: 'application',
117
+ subscriptions: 'application',
118
+ admin_customers: 'application',
119
+ admin_orders: 'application'
107
120
  }
108
121
 
109
122
  # SimpleForm Options
110
- # This Hash of options will be passed into any simple_form_for() calls
123
+ # This Hash of options will be passed into any client facing simple_form_for() calls
111
124
  config.simple_form_options = {}
125
+ config.admin_simple_form_options = {} # For the /admin/orders/new form
112
126
 
113
127
  # config.simple_form_options = {
114
- # :html => {:class => 'form-horizontal'},
115
- # :wrapper => :horizontal_form,
116
- # :wrapper_mappings => {
117
- # :boolean => :horizontal_boolean,
118
- # :check_boxes => :horizontal_radio_and_checkboxes,
119
- # :radio_buttons => :horizontal_radio_and_checkboxes
128
+ # html: {class: 'form-horizontal'},
129
+ # wrapper: :horizontal_form,
130
+ # wrapper_mappings: {
131
+ # boolean: :horizontal_boolean,
132
+ # check_boxes: :horizontal_radio_and_checkboxes,
133
+ # radio_buttons: :horizontal_radio_and_checkboxes
120
134
  # }
121
135
  # }
122
136
 
@@ -124,48 +138,63 @@ EffectiveOrders.setup do |config|
124
138
  # effective_orders will send out receipts to the buyer, seller and admins.
125
139
  # For all the emails, the same :subject_prefix will be prefixed. Leave as nil / empty string if you don't want any prefix
126
140
  #
127
- # The subject_for_admin_receipt, subject_for_buyer_receipt and subject_for_seller_receipt can be one of:
141
+ # The subject_for_admin_receipt, subject_for_buyer_receipt, subject_for_payment_request and
142
+ # subject_for_seller_receipt can be one of:
128
143
  # - nil / empty string to use the built in defaults
129
144
  # - A string with the full subject line for this email
130
145
  # - A Proc to create the subject line based on the email
131
146
  # In all three of these cases, the subject_prefix will still be used.
132
147
 
133
148
  # The Procs are the same for admin & buyer receipt, the seller Proc is different
134
- # :subject_for_admin_receipt => Proc.new { |order| "Order #{order.to_param} has been purchased"}
135
- # :subject_for_buyer_receipt => Proc.new { |order| "Order #{order.to_param} has been purchased"}
136
- # :subject_for_seller_receipt => Proc.new { |order, order_items, seller| "Order #{order.to_param} has been purchased"}
149
+ # subject_for_order_receipt_to_admin: Proc.new { |order| "Order #{order.to_param} has been purchased"}
150
+ # subject_for_order_receipt_to_buyer: Proc.new { |order| "Order #{order.to_param} has been purchased"}
151
+ # subject_for_payment_request_to_buyer: Proc.new { |order| "Pending Order #{order.to_param}"}
152
+ # subject_for_order_receipt_to_seller: Proc.new { |order, order_items, seller| "Order #{order.to_param} has been purchased"}
137
153
 
138
154
  config.mailer = {
139
- :send_order_receipt_to_admin => true,
140
- :send_order_receipt_to_buyer => true,
141
- :send_order_receipt_to_seller => true, # Only applies to StripeConnect
142
- :layout => 'effective_orders_mailer_layout',
143
- :admin_email => 'admin@example.com',
144
- :default_from => 'info@example.com',
145
- :subject_prefix => '[example]',
146
- :subject_for_admin_receipt => '',
147
- :subject_for_buyer_receipt => '',
148
- :subject_for_seller_receipt => '',
149
- :deliver_method => nil,
150
- :delayed_job_deliver => false
155
+ send_order_receipt_to_admin: true,
156
+ send_order_receipt_to_buyer: true,
157
+ send_order_receipt_to_seller: true, # Only applies to StripeConnect
158
+ send_payment_request_to_buyer: true,
159
+ send_pending_order_invoice_to_buyer: true,
160
+ send_order_receipts_when_marked_paid_by_admin: false,
161
+
162
+ subject_prefix: '[example]',
163
+ subject_for_order_receipt_to_admin: '',
164
+ subject_for_order_receipt_to_buyer: '',
165
+ subject_for_order_receipt_to_seller: '',
166
+ subject_for_pending_order_invoice_to_buyer: '',
167
+ subject_for_payment_request_to_buyer: '',
168
+
169
+ layout: 'effective_orders_mailer_layout',
170
+
171
+ default_from: 'info@example.com',
172
+ admin_email: 'admin@example.com',
173
+
174
+ deliver_method: nil, # :deliver (rails < 4.2), :deliver_now (rails >= 4.2) or :deliver_later
175
+ delayed_job_deliver: false
151
176
  }
152
177
 
178
+ #######################################
179
+ ### Payment Provider specific options
180
+ #######################################
181
+
153
182
  # Moneris configuration
154
183
  config.moneris_enabled = false
155
184
 
156
185
  if Rails.env.production?
157
186
  config.moneris = {
158
- :ps_store_id => '',
159
- :hpp_key => '',
160
- :hpp_url => 'https://www3.moneris.com/HPPDP/index.php',
161
- :verify_url => 'https://www3.moneris.com/HPPDP/verifyTxn.php'
187
+ ps_store_id: '',
188
+ hpp_key: '',
189
+ hpp_url: 'https://www3.moneris.com/HPPDP/index.php',
190
+ verify_url: 'https://www3.moneris.com/HPPDP/verifyTxn.php'
162
191
  }
163
192
  else
164
193
  config.moneris = {
165
- :ps_store_id => '',
166
- :hpp_key => '',
167
- :hpp_url => 'https://esqa.moneris.com/HPPDP/index.php',
168
- :verify_url => 'https://esqa.moneris.com/HPPDP/verifyTxn.php'
194
+ ps_store_id: '',
195
+ hpp_key: '',
196
+ hpp_url: 'https://esqa.moneris.com/HPPDP/index.php',
197
+ verify_url: 'https://esqa.moneris.com/HPPDP/verifyTxn.php'
169
198
  }
170
199
  end
171
200
 
@@ -174,25 +203,25 @@ EffectiveOrders.setup do |config|
174
203
 
175
204
  if Rails.env.production?
176
205
  config.paypal = {
177
- :seller_email => '',
178
- :secret => '',
179
- :cert_id => '',
180
- :paypal_url => 'https://www.paypal.com/cgi-bin/webscr',
181
- :currency => 'CAD',
182
- :paypal_cert => "#{Rails.root}/config/paypalcerts/production/paypal_cert.pem",
183
- :app_cert => "#{Rails.root}/config/paypalcerts/production/app_cert.pem",
184
- :app_key => "#{Rails.root}/config/paypalcerts/production/app_key.pem"
206
+ seller_email: '',
207
+ secret: '',
208
+ cert_id: '',
209
+ paypal_url: 'https://www.paypal.com/cgi-bin/webscr',
210
+ currency: 'CAD',
211
+ paypal_cert: "#{Rails.root}/config/paypalcerts/production/paypal_cert.pem",
212
+ app_cert: "#{Rails.root}/config/paypalcerts/production/app_cert.pem",
213
+ app_key: "#{Rails.root}/config/paypalcerts/production/app_key.pem"
185
214
  }
186
215
  else
187
216
  config.paypal = {
188
- :seller_email => '',
189
- :secret => '',
190
- :cert_id => '',
191
- :paypal_url => 'https://www.sandbox.paypal.com/cgi-bin/webscr',
192
- :currency => 'CAD',
193
- :paypal_cert => "#{Rails.root}/config/paypalcerts/#{Rails.env}/paypal_cert.pem",
194
- :app_cert => "#{Rails.root}/config/paypalcerts/#{Rails.env}/app_cert.pem",
195
- :app_key => "#{Rails.root}/config/paypalcerts/#{Rails.env}/app_key.pem"
217
+ seller_email: '',
218
+ secret: '',
219
+ cert_id: '',
220
+ paypal_url: 'https://www.sandbox.paypal.com/cgi-bin/webscr',
221
+ currency: 'CAD',
222
+ paypal_cert: "#{Rails.root}/config/paypalcerts/#{Rails.env}/paypal_cert.pem",
223
+ app_cert: "#{Rails.root}/config/paypalcerts/#{Rails.env}/app_cert.pem",
224
+ app_key: "#{Rails.root}/config/paypalcerts/#{Rails.env}/app_key.pem"
196
225
  }
197
226
  end
198
227
 
@@ -204,21 +233,48 @@ EffectiveOrders.setup do |config|
204
233
 
205
234
  if Rails.env.production?
206
235
  config.stripe = {
207
- :secret_key => '',
208
- :publishable_key => '',
209
- :currency => 'usd',
210
- :site_title => 'My Site',
211
- :site_image => '', # A relative URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.
212
- :connect_client_id => ''
236
+ secret_key: '',
237
+ publishable_key: '',
238
+ currency: 'usd',
239
+ site_title: 'My Site',
240
+ site_image: '', # A relative URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.
241
+ connect_client_id: ''
213
242
  }
214
243
  else
215
244
  config.stripe = {
216
- :secret_key => '',
217
- :publishable_key => '',
218
- :currency => 'usd',
219
- :site_title => 'My Development Site', # Displayed on the Embedded Stripe Form
220
- :site_image => '', # A relative URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.
221
- :connect_client_id => ''
245
+ secret_key: '',
246
+ publishable_key: '',
247
+ currency: 'usd',
248
+ site_title: 'My Development Site', # Displayed on the Embedded Stripe Form
249
+ site_image: '', # A relative URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px.
250
+ connect_client_id: ''
251
+ }
252
+ end
253
+
254
+ # CCBill configuration
255
+ config.ccbill_enabled = false
256
+
257
+ # CCBill Dynamic Pricing documentation describes these variables:
258
+ # https://www.ccbill.com/cs/wiki/tiki-index.php?page=Dynamic+Pricing+User+Guide
259
+ if Rails.env.production?
260
+ config.ccbill = {
261
+ client_accnum: '',
262
+ client_subacc: '0000', # initial sub account
263
+ # Get this from CCBill Admin dashboard after setting up a form
264
+ form_name: '211cc', # default credit card form
265
+ # https://www.ccbill.com/cs/wiki/tiki-index.php?page=Webhooks+User+Guide#Appendix_A:_Currency_Codes
266
+ currency_code: '840', # USD
267
+ # You'll need to get this salt after having CCBill tech support set up dynamic pricing
268
+ # https://www.ccbill.com/cs/wiki/tiki-index.php?page=Dynamic+Pricing+User+Guide#Generating_the_MD5_Hash
269
+ dynamic_pricing_salt: ''
270
+ }
271
+ else
272
+ config.ccbill = {
273
+ client_accnum: '',
274
+ client_subacc: '0000',
275
+ form_name: '211cc',
276
+ currency_code: '840',
277
+ dynamic_pricing_salt: ''
222
278
  }
223
279
  end
224
280
 
@@ -230,4 +286,13 @@ EffectiveOrders.setup do |config|
230
286
  service: nil, # an EffectiveOrders::AppCheckout type object
231
287
  declined_flash: "Payment was unsuccessful. Please try again."
232
288
  }
289
+
290
+
291
+ # Pay by Cheque configuration
292
+ config.cheque_enabled = false
293
+
294
+ config.cheque = {
295
+ confirm: 'Your order will not be considered purchased until we receive your cheque. Proceed with pay by cheque?'
296
+ }
297
+
233
298
  end
@@ -3,42 +3,56 @@
3
3
  # to see a preview of the following 3 emails:
4
4
 
5
5
  class EffectiveOrdersMailerPreview < ActionMailer::Preview
6
- def order_receipt_to_buyer
7
- Effective::OrdersMailer.order_receipt_to_buyer(build_preview_order)
8
- end
9
-
10
6
  def order_receipt_to_admin
11
7
  Effective::OrdersMailer.order_receipt_to_admin(build_preview_order)
12
8
  end
13
9
 
10
+ def order_receipt_to_buyer
11
+ Effective::OrdersMailer.order_receipt_to_buyer(build_preview_order)
12
+ end
13
+
14
14
  # This email is only sent to sellers having sold items via StripeConnect
15
15
  def order_receipt_to_seller
16
16
  order = build_preview_order
17
17
  Effective::OrdersMailer.order_receipt_to_seller(order, preview_customer, order.order_items)
18
18
  end
19
19
 
20
+ def payment_request_to_buyer
21
+ Effective::OrdersMailer.payment_request_to_buyer(build_preview_order)
22
+ end
23
+
24
+ def pending_order_invoice_to_buyer
25
+ Effective::OrdersMailer.pending_order_invoice_to_buyer(build_preview_order)
26
+ end
27
+
28
+ def order_error
29
+ Effective::OrdersMailer.order_error(order: build_preview_order, error: "Something didn't work out")
30
+ end
31
+
20
32
  protected
21
33
 
22
34
  def build_preview_order
23
- order = Effective::Order.new()
35
+ order = Effective::Order.new
24
36
  order.user = preview_user
25
37
  preview_order_items.each { |atts| order.order_items.build(atts) }
38
+ order.valid?
26
39
  order
27
40
  end
28
41
 
42
+ def build_address
43
+ Effective::Address.new(category: 'billing', full_name: 'Valued Customer', address1: '1234 Fake Street', address2: 'Suite 200', city: 'Edmonton', state_code: 'AB', country_code: 'CA', postal_code: 'T5T 2T1')
44
+ end
45
+
29
46
  private
30
47
 
31
48
  # We're building Effective::OrderItems directly rather than creating acts_as_purchasable objects
32
49
  # so that this mailer will not have to guess at your app's acts_as_purchasable objects
33
50
  def preview_order_items
34
- tax_rate = (EffectiveOrders.tax_rate_method.call(Object.new()) rescue -1)
35
- tax_rate = 0.05 if tax_rate < 0.0
36
-
37
51
  [
38
- {title: 'Item One', quantity: 2, price: 999, tax_exempt: false, tax_rate: tax_rate},
39
- {title: 'Item Two', quantity: 1, price: 25000, tax_exempt: false, tax_rate: tax_rate},
40
- {title: 'Item Three', quantity: 1, price: 8999, tax_exempt: false, tax_rate: tax_rate},
41
- {title: 'Item Four', quantity: 1, price: 100000, tax_exempt: false, tax_rate: tax_rate}
52
+ {title: 'Item One', quantity: 2, price: 999, tax_exempt: false},
53
+ {title: 'Item Two', quantity: 1, price: 25000, tax_exempt: false},
54
+ {title: 'Item Three', quantity: 1, price: 8999, tax_exempt: false},
55
+ {title: 'Item Four', quantity: 1, price: 100000, tax_exempt: false}
42
56
  ]
43
57
  end
44
58
 
@@ -51,11 +65,12 @@ class EffectiveOrdersMailerPreview < ActionMailer::Preview
51
65
  user.first_name = 'Valued'
52
66
  user.last_name = 'Customer'
53
67
  end
68
+
69
+ user.billing_address = build_address if user.respond_to?(:billing_address=)
54
70
  end
55
71
  end
56
72
 
57
73
  def preview_customer
58
74
  Effective::Customer.new(user: preview_user)
59
75
  end
60
-
61
76
  end
@@ -0,0 +1,242 @@
1
+ require 'spec_helper'
2
+
3
+ describe Admin::OrdersController, type: :controller do
4
+ routes { EffectiveOrders::Engine.routes }
5
+
6
+ let!(:user1) { FactoryGirl.create(:user, email: 'bbb@example.com') }
7
+ let!(:user2) { FactoryGirl.create(:user, email: 'ccc@example.com') }
8
+ let!(:user3) { FactoryGirl.create(:user, email: 'aaa@example.com') }
9
+ let(:cart) { FactoryGirl.create(:cart, user: user1) }
10
+
11
+ before { sign_in cart.user }
12
+
13
+ describe 'GET #new' do
14
+ it 'should render admin new order page successfully' do
15
+ get :new
16
+
17
+ expect(response).to be_successful
18
+ expect(response).to render_template :new
19
+ expect(assigns(:order)).to be_an Effective::Order
20
+ expect(assigns(:order)).to be_new_record
21
+ expect(assigns(:page_title)).to eq 'New Order'
22
+ end
23
+ end
24
+
25
+ describe 'POST #create' do
26
+ let(:user1) { FactoryGirl.create(:user, email: 'bbb@example.com', billing_address: FactoryGirl.create(:address), shipping_address: FactoryGirl.create(:address)) }
27
+
28
+ context 'when success' do
29
+ let(:order_params) { { effective_order: { user_id: user1.id, order_items_attributes: { '0' => { purchasable_attributes: { title: 'test product 1', price: '10000', tax_exempt: '1' }, quantity: '2', '_destroy' => 'false' }, '1' => { purchasable_attributes: { title: 'test product 2', price: '30000', tax_exempt: '0' }, quantity: '3', '_destroy' => 'false' } }, send_payment_request_to_buyer: '1' } } }
30
+
31
+ shared_context 'creates objects in db correctly' do
32
+ it 'should create new custom order with pending state' do
33
+ expect { post :create, order_params.merge(commit: button_pressed) }.to change { Effective::Order.count }.from(0).to(1)
34
+
35
+ expect(assigns(:order)).to be_persisted
36
+ expect(assigns(:order).pending?).to be_truthy
37
+ expect(assigns(:order).user).to eq user1
38
+ expect(assigns(:order).billing_address).to eq user1.billing_address
39
+ expect(assigns(:order).shipping_address).to eq user1.shipping_address
40
+
41
+ expect(assigns(:order).order_items.count).to eq 2
42
+
43
+ first_item = assigns(:order).order_items.sort.first
44
+ expect(first_item).to be_persisted
45
+ expect(first_item.title).to eq 'test product 1'
46
+ expect(first_item.quantity).to eq 2
47
+ expect(first_item.price).to eq 10000
48
+ expect(first_item.tax_exempt).to be_truthy
49
+
50
+ second_item = assigns(:order).order_items.sort.last
51
+ expect(second_item).to be_persisted
52
+ expect(second_item.title).to eq 'test product 2'
53
+ expect(second_item.quantity).to eq 3
54
+ expect(second_item.price).to eq 30000
55
+ expect(second_item.tax_exempt).to be_falsey
56
+ end
57
+
58
+ it 'should create new effective products' do
59
+ expect { post :create, order_params.merge(commit: button_pressed) }.to change { Effective::Product.count }.from(0).to(2)
60
+
61
+ first_product = Effective::Product.all.sort.first
62
+ expect(first_product.title).to eq 'test product 1'
63
+ expect(first_product.price).to eq 10000
64
+
65
+ second_product = Effective::Product.all.sort.last
66
+ expect(second_product.title).to eq 'test product 2'
67
+ expect(second_product.price).to eq 30000
68
+ end
69
+ end
70
+
71
+ context 'when "Save" button is pressed' do
72
+ let(:button_pressed) { 'Save' }
73
+
74
+ it_should_behave_like 'creates objects in db correctly'
75
+
76
+ it 'should redirect to admin orders index page with success message' do
77
+ post :create, order_params.merge(commit: button_pressed)
78
+
79
+ expect(response).to be_redirect
80
+ expect(response).to redirect_to EffectiveOrders::Engine.routes.url_helpers.admin_order_path(assigns(:order))
81
+ expect(flash[:success]).to eq "Successfully created order. #{assigns(:order).user.email} has been sent a request for payment."
82
+ end
83
+ end
84
+
85
+ context 'when "Save and Add New" button is pressed' do
86
+ let(:button_pressed) { 'Save and Add New' }
87
+
88
+ it_should_behave_like 'creates objects in db correctly'
89
+
90
+ it 'should redirect to admin new order page with success message' do
91
+ post :create, order_params.merge(commit: button_pressed)
92
+
93
+ expect(response).to be_redirect
94
+ expect(response).to redirect_to EffectiveOrders::Engine.routes.url_helpers.new_admin_order_path
95
+ expect(flash[:success]).to eq "Successfully created order. #{assigns(:order).user.email} has been sent a request for payment."
96
+ end
97
+ end
98
+ end
99
+
100
+ context 'when failed' do
101
+ let(:order_params) { { effective_order: { user_id: user1.id, order_items_attributes: { '0' => { purchasable_attributes: { title: 'test product 1', price: '0', tax_exempt: '1' }, quantity: '2', '_destroy' => 'false' } } } } }
102
+
103
+ shared_context 'does not create objects in db and redirects to admin new order page with danger message' do
104
+ it 'should not create order' do
105
+ expect { post :create, order_params.merge(commit: button_pressed) }.not_to change { Effective::Order.count }
106
+
107
+ expect(assigns(:order)).to be_new_record
108
+ expect(assigns(:order).valid?).to be_falsey
109
+ expect(assigns(:order).pending?).to be_truthy
110
+ expect(assigns(:order).user).to eq user1
111
+ expect(assigns(:order).billing_address).to eq user1.billing_address
112
+ expect(assigns(:order).shipping_address).to eq user1.shipping_address
113
+
114
+ expect(assigns(:order).order_items.to_a.count).to eq 1
115
+
116
+ item = assigns(:order).order_items.first
117
+ expect(item).to be_new_record
118
+ expect(item.valid?).to be_falsey
119
+ expect(item.title).to eq 'test product 1'
120
+ expect(item.quantity).to eq 2
121
+ expect(item.price).to eq 0
122
+ expect(item.tax_exempt).to be_truthy
123
+ end
124
+
125
+ it 'should not create product' do
126
+ expect { post :create, order_params.merge(commit: button_pressed) }.not_to change { Effective::Product.count }
127
+ end
128
+
129
+ it 'should render admin new order page with danger message' do
130
+ post :create, order_params.merge(commit: button_pressed)
131
+
132
+ expect(response).to be_successful
133
+ expect(response).to render_template :new
134
+ expect(assigns(:page_title)).to eq 'New Order'
135
+ expect(flash[:danger]).to eq 'Unable to create order'
136
+ end
137
+ end
138
+
139
+ context 'when "Save" button is pressed' do
140
+ let(:button_pressed) { 'Save' }
141
+
142
+ it_should_behave_like 'does not create objects in db and redirects to admin new order page with danger message'
143
+ end
144
+
145
+ context 'when "Save and Add New" button is pressed' do
146
+ let(:button_pressed) { 'Save and Add New' }
147
+
148
+ it_should_behave_like 'does not create objects in db and redirects to admin new order page with danger message'
149
+ end
150
+ end
151
+ end
152
+
153
+ describe 'POST #mark_as_paid' do
154
+ let(:order) { FactoryGirl.create(:pending_order) }
155
+
156
+ before { request.env['HTTP_REFERER'] = 'where_i_came_from' }
157
+
158
+ context 'when success' do
159
+ it 'should update order state and redirect to orders admin index page with success message' do
160
+ post :mark_as_paid, id: order.to_param
161
+
162
+ expect(response).to be_redirect
163
+ expect(response).to redirect_to EffectiveOrders::Engine.routes.url_helpers.admin_order_path(assigns(:order))
164
+ expect(assigns(:order)).to eq order
165
+ expect(assigns(:order).purchased?).to be_truthy
166
+ expect(assigns(:order).payment).to eq(details: 'Marked as paid by admin')
167
+ expect(flash[:success]).to eq 'Order marked as paid successfully'
168
+ end
169
+ end
170
+
171
+ context 'when failed' do
172
+ before { Effective::Order.any_instance.stub(:purchase!).and_return(false) }
173
+
174
+ it 'should redirect back with danger message' do
175
+ post :mark_as_paid, id: order.to_param
176
+
177
+ expect(response).to be_redirect
178
+ expect(response).to redirect_to 'where_i_came_from'
179
+ expect(assigns(:order)).to eq order
180
+ expect(assigns(:order).purchased?).to be_falsey
181
+ expect(flash[:danger]).to eq 'Unable to mark order as paid'
182
+ end
183
+ end
184
+ end
185
+
186
+ describe 'POST #send_payment_request' do
187
+ let(:user) { FactoryGirl.create(:user, email: 'user@example.com') }
188
+ let(:order) { FactoryGirl.create(:order, user: user) }
189
+
190
+ context 'when success' do
191
+ before { Effective::Order.any_instance.should_receive(:send_payment_request_to_buyer!).once.and_return(true) }
192
+
193
+ context 'when referrer page is present' do
194
+ before { request.env['HTTP_REFERER'] = 'where_i_came_from' }
195
+
196
+ it 'should redirect to previous page with success message' do
197
+ post :send_payment_request, id: order.to_param
198
+
199
+ expect(response).to be_redirect
200
+ expect(response).to redirect_to 'where_i_came_from'
201
+ expect(flash[:success]).to eq 'Successfully sent payment request to user@example.com'
202
+ end
203
+ end
204
+
205
+ context 'when referrer page is not present' do
206
+ it 'should redirect to admin order show page with success message' do
207
+ post :send_payment_request, id: order.to_param
208
+
209
+ expect(response).to be_redirect
210
+ expect(response).to redirect_to EffectiveOrders::Engine.routes.url_helpers.admin_order_path(order)
211
+ expect(flash[:success]).to eq 'Successfully sent payment request to user@example.com'
212
+ end
213
+ end
214
+ end
215
+
216
+ context 'when failed' do
217
+ before { Effective::Order.any_instance.should_receive(:send_payment_request_to_buyer!).once.and_return(false) }
218
+
219
+ context 'when referrer page is present' do
220
+ before { request.env['HTTP_REFERER'] = 'where_i_came_from' }
221
+
222
+ it 'should redirect to previous page with danger message' do
223
+ post :send_payment_request, id: order.to_param
224
+
225
+ expect(response).to be_redirect
226
+ expect(response).to redirect_to 'where_i_came_from'
227
+ expect(flash[:danger]).to eq 'Unable to send payment request'
228
+ end
229
+ end
230
+
231
+ context 'when referrer page is not present' do
232
+ it 'should redirect to admin order show page with danger message' do
233
+ post :send_payment_request, id: order.to_param
234
+
235
+ expect(response).to be_redirect
236
+ expect(response).to redirect_to EffectiveOrders::Engine.routes.url_helpers.admin_order_path(order)
237
+ expect(flash[:danger]).to eq 'Unable to send payment request'
238
+ end
239
+ end
240
+ end
241
+ end
242
+ end