effective_orders 1.8.1 → 2.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 (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