effective_orders 2.2.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +124 -84
  4. data/app/assets/javascripts/effective_orders/customers.js.coffee +39 -0
  5. data/app/assets/javascripts/effective_orders/providers/{stripe_charges.js.coffee → stripe.js.coffee} +15 -13
  6. data/app/assets/javascripts/effective_orders/subscriptions.js.coffee +73 -0
  7. data/app/assets/stylesheets/effective_orders.scss +2 -1
  8. data/app/assets/stylesheets/effective_orders/_order.scss +16 -8
  9. data/app/assets/stylesheets/effective_orders/_subscriptions.scss +14 -0
  10. data/app/controllers/admin/customers_controller.rb +11 -8
  11. data/app/controllers/admin/order_items_controller.rb +4 -8
  12. data/app/controllers/admin/orders_controller.rb +133 -87
  13. data/app/controllers/effective/carts_controller.rb +18 -8
  14. data/app/controllers/effective/concerns/purchase.rb +39 -0
  15. data/app/controllers/effective/customers_controller.rb +43 -0
  16. data/app/controllers/effective/orders_controller.rb +73 -119
  17. data/app/controllers/effective/providers/app_checkout.rb +3 -1
  18. data/app/controllers/effective/providers/ccbill.rb +4 -6
  19. data/app/controllers/effective/providers/cheque.rb +20 -11
  20. data/app/controllers/effective/providers/free.rb +33 -0
  21. data/app/controllers/effective/providers/mark_as_paid.rb +33 -0
  22. data/app/controllers/effective/providers/moneris.rb +9 -17
  23. data/app/controllers/effective/providers/paypal.rb +4 -6
  24. data/app/controllers/effective/providers/pretend.rb +4 -4
  25. data/app/controllers/effective/providers/refund.rb +39 -0
  26. data/app/controllers/effective/providers/stripe.rb +19 -40
  27. data/app/controllers/effective/providers/stripe_connect.rb +2 -6
  28. data/app/controllers/effective/webhooks_controller.rb +44 -95
  29. data/app/datatables/effective_customers_datatable.rb +21 -29
  30. data/app/datatables/effective_order_items_datatable.rb +77 -79
  31. data/app/datatables/effective_orders_datatable.rb +67 -57
  32. data/app/helpers/effective_carts_helper.rb +17 -14
  33. data/app/helpers/effective_orders_helper.rb +40 -56
  34. data/app/helpers/effective_paypal_helper.rb +3 -3
  35. data/app/helpers/effective_stripe_helper.rb +47 -18
  36. data/app/helpers/effective_subscriptions_helper.rb +79 -0
  37. data/app/mailers/effective/orders_mailer.rb +125 -2
  38. data/app/models/concerns/acts_as_purchasable.rb +23 -33
  39. data/app/models/concerns/acts_as_subscribable.rb +68 -0
  40. data/app/models/concerns/acts_as_subscribable_buyer.rb +22 -0
  41. data/app/models/effective/cart.rb +53 -24
  42. data/app/models/effective/cart_item.rb +6 -12
  43. data/app/models/effective/customer.rb +51 -54
  44. data/app/models/effective/order.rb +160 -147
  45. data/app/models/effective/order_item.rb +18 -21
  46. data/app/models/effective/product.rb +7 -7
  47. data/app/models/effective/providers/ccbill_postback.rb +1 -1
  48. data/app/models/effective/providers/stripe_charge.rb +8 -19
  49. data/app/models/effective/subscripter.rb +230 -0
  50. data/app/models/effective/subscription.rb +27 -76
  51. data/app/models/effective/tax_rate_calculator.rb +10 -7
  52. data/app/views/admin/customers/_actions.html.haml +1 -2
  53. data/app/views/admin/customers/index.html.haml +1 -1
  54. data/app/views/admin/customers/show.html.haml +6 -0
  55. data/app/views/admin/orders/_actions.html.haml +9 -7
  56. data/app/views/admin/orders/_form.html.haml +11 -7
  57. data/app/views/admin/orders/_order_actions.html.haml +2 -1
  58. data/app/views/admin/orders/_order_item_fields.html.haml +1 -1
  59. data/app/views/admin/orders/edit.html.haml +4 -0
  60. data/app/views/admin/orders/index.html.haml +1 -4
  61. data/app/views/admin/orders/new.html.haml +1 -1
  62. data/app/views/admin/orders/show.html.haml +5 -6
  63. data/app/views/effective/carts/_cart.html.haml +2 -2
  64. data/app/views/effective/carts/show.html.haml +2 -2
  65. data/app/views/effective/customers/_customer.html.haml +152 -0
  66. data/app/views/effective/customers/_fields.html.haml +12 -0
  67. data/app/views/effective/customers/_form.html.haml +13 -0
  68. data/app/views/effective/customers/edit.html.haml +3 -0
  69. data/app/views/effective/orders/_checkout_step1.html.haml +8 -15
  70. data/app/views/effective/orders/_checkout_step2.html.haml +34 -21
  71. data/app/views/effective/orders/_order.html.haml +8 -9
  72. data/app/views/effective/orders/_order_actions.html.haml +7 -8
  73. data/app/views/effective/orders/_order_header.html.haml +1 -1
  74. data/app/views/effective/orders/_order_items.html.haml +11 -5
  75. data/app/views/effective/orders/_order_note.html.haml +4 -7
  76. data/app/views/effective/orders/_orders_table.html.haml +26 -26
  77. data/app/views/effective/orders/app_checkout/_form.html.haml +2 -2
  78. data/app/views/effective/orders/ccbill/_form.html.haml +1 -1
  79. data/app/views/effective/orders/cheque/_form.html.haml +3 -1
  80. data/app/views/effective/orders/declined.html.haml +1 -1
  81. data/app/views/effective/orders/{checkout_step1.html.haml → edit.html.haml} +0 -0
  82. data/app/views/effective/orders/free/_form.html.haml +4 -0
  83. data/app/views/effective/orders/index.html.haml +2 -4
  84. data/app/views/effective/orders/mark_as_paid/_form.html.haml +32 -0
  85. data/app/views/effective/orders/moneris/_form.html.haml +6 -6
  86. data/app/views/effective/orders/{checkout_step2.html.haml → new.html.haml} +1 -1
  87. data/app/views/effective/orders/paypal/_form.html.haml +2 -2
  88. data/app/views/effective/orders/pretend/_form.html.haml +2 -2
  89. data/app/views/effective/orders/purchased.html.haml +3 -0
  90. data/app/views/effective/orders/refund/_form.html.haml +32 -0
  91. data/app/views/effective/orders/show.html.haml +4 -1
  92. data/app/views/effective/orders/stripe/_form.html.haml +5 -5
  93. data/app/views/effective/orders_mailer/subscription_canceled.html.haml +9 -0
  94. data/app/views/effective/orders_mailer/subscription_payment_failed.html.haml +9 -0
  95. data/app/views/effective/orders_mailer/subscription_payment_succeeded.html.haml +9 -0
  96. data/app/views/effective/orders_mailer/subscription_trial_expired.html.haml +5 -0
  97. data/app/views/effective/orders_mailer/subscription_trial_expiring.html.haml +7 -0
  98. data/app/views/effective/subscriptions/_fields.html.haml +16 -0
  99. data/app/views/effective/subscriptions/_plan.html.haml +21 -0
  100. data/app/views/layouts/effective_orders_mailer_layout.html.haml +6 -8
  101. data/config/effective_orders.rb +41 -20
  102. data/config/routes.rb +48 -48
  103. data/db/migrate/01_create_effective_orders.rb.erb +19 -5
  104. data/lib/effective_orders.rb +78 -42
  105. data/lib/effective_orders/engine.rb +36 -82
  106. data/lib/effective_orders/version.rb +1 -1
  107. data/lib/generators/effective_orders/install_generator.rb +2 -2
  108. data/lib/generators/templates/effective_orders_mailer_preview.rb +39 -4
  109. data/lib/tasks/effective_orders_tasks.rake +42 -0
  110. data/spec/controllers/carts_controller_spec.rb +1 -1
  111. data/spec/controllers/moneris_orders_controller_spec.rb +4 -4
  112. data/spec/controllers/orders_controller_spec.rb +4 -4
  113. data/spec/controllers/stripe_orders_controller_spec.rb +2 -2
  114. data/spec/controllers/webhooks_controller_spec.rb +1 -1
  115. data/spec/dummy/config/initializers/effective_orders.rb +1 -7
  116. data/spec/dummy/db/schema.rb +1 -0
  117. data/spec/dummy/db/test.sqlite3 +0 -0
  118. data/spec/dummy/log/test.log +3 -0
  119. data/spec/models/acts_as_purchasable_spec.rb +0 -56
  120. data/spec/models/customer_spec.rb +3 -3
  121. data/spec/models/order_spec.rb +2 -2
  122. data/spec/spec_helper.rb +1 -1
  123. data/spec/support/factories.rb +2 -1
  124. metadata +37 -49
  125. data/active_admin/effective_carts.rb +0 -14
  126. data/active_admin/effective_orders.rb +0 -112
  127. data/app/assets/javascripts/effective_orders/providers/stripe_subscriptions.js.coffee +0 -28
  128. data/app/controllers/concerns/acts_as_active_admin_controller.rb +0 -69
  129. data/app/controllers/effective/subscriptions_controller.rb +0 -126
  130. data/app/models/effective/datatables/customers.rb +0 -40
  131. data/app/models/effective/datatables/order_items.rb +0 -101
  132. data/app/models/effective/datatables/orders.rb +0 -91
  133. data/app/models/inputs/price_field.rb +0 -63
  134. data/app/models/inputs/price_form_input.rb +0 -7
  135. data/app/models/inputs/price_formtastic_input.rb +0 -9
  136. data/app/models/inputs/price_input.rb +0 -19
  137. data/app/models/inputs/price_simple_form_input.rb +0 -8
  138. data/app/views/admin/orders/_form_mark_as_paid.html.haml +0 -33
  139. data/app/views/admin/orders/_order_payment_details.html.haml +0 -5
  140. data/app/views/admin/orders/mark_as_paid.html.haml +0 -7
  141. data/app/views/effective/orders/stripe/_subscription_fields.html.haml +0 -7
  142. data/app/views/effective/subscriptions/index.html.haml +0 -22
  143. data/app/views/effective/subscriptions/new.html.haml +0 -9
  144. data/app/views/effective/subscriptions/show.html.haml +0 -49
  145. data/db/upgrade/02_upgrade_effective_orders_from03x.rb.erb +0 -29
  146. data/db/upgrade/03_upgrade_effective_orders_from1x.rb.erb +0 -98
  147. data/db/upgrade/upgrade_price_column_on_table.rb.erb +0 -17
  148. data/lib/generators/effective_orders/upgrade_from03x_generator.rb +0 -31
  149. data/lib/generators/effective_orders/upgrade_from1x_generator.rb +0 -27
  150. data/lib/generators/effective_orders/upgrade_price_column_generator.rb +0 -30
@@ -1,38 +1,30 @@
1
- unless Gem::Version.new(EffectiveDatatables::VERSION) < Gem::Version.new('3.0')
2
- class EffectiveCustomersDatatable < Effective::Datatable
3
- datatable do
4
- order :email
1
+ class EffectiveCustomersDatatable < Effective::Datatable
2
+ datatable do
5
3
 
6
- col :id, visible: false
7
- col :email, sql_column: 'users.email' do |user|
8
- mail_to user.email, user.email
9
- end
4
+ col :id, visible: false
5
+ #col 'user.email'
10
6
 
11
- if EffectiveOrders.stripe_enabled
12
- col :stripe_customer_id
13
- col :stripe_active_card
14
- end
15
-
16
- if EffectiveOrders.stripe_connect_enabled
17
- col :stripe_connect_access_token
18
- end
19
-
20
- col :subscription_types, sql_column: 'subscription_types'
7
+ if EffectiveOrders.stripe_enabled
8
+ col :stripe_customer_id
9
+ col :active_card
10
+ end
21
11
 
22
- actions_col partial: 'admin/customers/actions', partial_as: :customer
12
+ if EffectiveOrders.stripe_connect_enabled
13
+ col :stripe_connect_access_token
23
14
  end
24
15
 
25
- collection do
26
- Effective::Customer.customers.distinct
27
- .joins(:user, :subscriptions)
28
- .select('customers.*, users.email AS email')
29
- .select("array_to_string(array(#{Effective::Subscription.purchased.select('subscriptions.stripe_plan_id').where('subscriptions.customer_id = customers.id').to_sql}), ' ,') AS subscription_types")
30
- .group('customers.id, subscriptions.stripe_plan_id, users.email')
16
+ actions_col do |customer|
17
+ link_to('Manage', "https://dashboard.stripe.com/#{'test/' if Rails.env.development?}customers/#{customer.stripe_customer_id}")
31
18
  end
32
19
 
33
- # def search_column(collection, table_column, search_term)
34
- # return collection.where('subscriptions.stripe_plan_id ILIKE ?', "%#{search_term}%") if table_column[:name] == 'subscription_types'
35
- # super
36
- # end
37
20
  end
21
+
22
+ collection do
23
+ Effective::Customer.joins(:user).all
24
+ end
25
+
26
+ # def search_column(collection, table_column, search_term)
27
+ # return collection.where('subscriptions.stripe_plan_id ILIKE ?', "%#{search_term}%") if table_column[:name] == 'subscription_types'
28
+ # super
29
+ # end
38
30
  end
@@ -1,101 +1,99 @@
1
- unless Gem::Version.new(EffectiveDatatables::VERSION) < Gem::Version.new('3.0')
2
- class EffectiveOrderItemsDatatable < Effective::Datatable
3
- datatable do
4
- order :purchased_at, :desc
1
+ class EffectiveOrderItemsDatatable < Effective::Datatable
2
+ datatable do
3
+ order :purchased_at, :desc
5
4
 
6
- col(:purchased_at, sql_column: 'orders.purchased_at') do |order_item|
7
- Time.at(order_item[:purchased_at]).in_time_zone if order_item[:purchased_at].present?
8
- end
5
+ col(:purchased_at, sql_column: 'orders.purchased_at') do |order_item|
6
+ Time.at(order_item[:purchased_at]).in_time_zone if order_item[:purchased_at].present?
7
+ end
9
8
 
10
- col :id, visible: false
11
-
12
- col :order
13
-
14
- # if effectiveorders.obfuscate_order_ids
15
- # col(:order, type: :obfuscated_id) do |order_item|
16
- # obfuscated_id = effective::order.obfuscate(order_item[:order_id])
17
- # link_to(obfuscated_id, (datatables_admin_path? ? effective_orders.admin_order_path(obfuscated_id) : effective_orders.order_path(obfuscated_id)))
18
- # end
19
- # else
20
- # col(:order) do |order_item|
21
- # link_to(order_item.to_param, (datatables_admin_path? ? effective_orders.admin_order_path(order_item.to_param) : effective_orders.order_path(order_item.to_param)))
22
- # end
23
- # end
24
-
25
- unless attributes[:user_id]
26
- col :email, sql_column: 'users.email', label: 'Buyer Email' do |order_item|
27
- link_to order_item[:email], (edit_admin_user_path(order_item[:user_id]) rescue admin_user_path(order_item[:user_id]) rescue '#')
28
- end
29
- end
9
+ col :id, visible: false
30
10
 
31
- if EffectiveOrders.require_billing_address && attributes[:user_id].blank?
32
- col :buyer_name, sort: false, label: 'Buyer Name' do |order_item|
33
- (order_item[:buyer_name] || '').split('!!SEP!!').find(&:present?)
34
- end
35
- end
11
+ col :order
12
+
13
+ # if effectiveorders.obfuscate_order_ids
14
+ # col(:order, type: :obfuscated_id) do |order_item|
15
+ # obfuscated_id = effective::order.obfuscate(order_item[:order_id])
16
+ # link_to(obfuscated_id, (datatables_admin_path? ? effective_orders.admin_order_path(obfuscated_id) : effective_orders.order_path(obfuscated_id)))
17
+ # end
18
+ # else
19
+ # col(:order) do |order_item|
20
+ # link_to(order_item.to_param, (datatables_admin_path? ? effective_orders.admin_order_path(order_item.to_param) : effective_orders.order_path(order_item.to_param)))
21
+ # end
22
+ # end
36
23
 
37
- col :purchase_state, sql_column: 'orders.purchase_state', search: { collection: [%w(abandoned abandoned), [EffectiveOrders::PURCHASED, EffectiveOrders::PURCHASED], [EffectiveOrders::DECLINED, EffectiveOrders::DECLINED]], selected: EffectiveOrders::PURCHASED } do |order_item|
38
- order_item[:purchase_state] || 'abandoned'
24
+ unless attributes[:user_id]
25
+ col :email, sql_column: 'users.email', label: 'Buyer Email' do |order_item|
26
+ link_to order_item[:email], (edit_admin_user_path(order_item[:user_id]) rescue admin_user_path(order_item[:user_id]) rescue '#')
39
27
  end
28
+ end
40
29
 
41
- col :title do |order_item|
42
- order_item.quantity == 1 ? order_item.title : "#{order_item.title} (#{order_item.quantity} purchased)"
30
+ if EffectiveOrders.require_billing_address && attributes[:user_id].blank?
31
+ col :buyer_name, sort: false, label: 'Buyer Name' do |order_item|
32
+ (order_item[:buyer_name] || '').split('!!SEP!!').find(&:present?)
43
33
  end
34
+ end
44
35
 
45
- # col :subtotal, as: :price
46
- # col :tax, as: :price
47
- # col :total, as: :price
36
+ col :purchase_state, sql_column: 'orders.purchase_state', search: { collection: [%w(abandoned abandoned), [EffectiveOrders::PURCHASED, EffectiveOrders::PURCHASED], [EffectiveOrders::DECLINED, EffectiveOrders::DECLINED]], selected: EffectiveOrders::PURCHASED } do |order_item|
37
+ order_item[:purchase_state] || 'abandoned'
38
+ end
48
39
 
49
- col :created_at, visible: false
50
- col :updated_at, visible: false
40
+ col :title do |order_item|
41
+ order_item.quantity == 1 ? order_item.title : "#{order_item.title} (#{order_item.quantity} purchased)"
51
42
  end
52
43
 
53
- collection do
54
- collection = Effective::OrderItem.unscoped
55
- .joins(order: :user)
56
- .select('order_items.*, orders.*, users.email AS email')
57
- .select("#{query_subtotal} AS subtotal, #{query_tax} AS tax, #{query_total} AS total")
58
- .group('order_items.id, orders.id, users.email')
44
+ # col :subtotal, as: :price
45
+ # col :tax, as: :price
46
+ # col :total, as: :price
59
47
 
60
- if EffectiveOrders.require_billing_address && defined?(EffectiveAddresses)
61
- addresses_tbl = EffectiveAddresses.addresses_table_name
48
+ col :created_at, visible: false
49
+ col :updated_at, visible: false
50
+ end
62
51
 
63
- collection = collection
64
- .joins("LEFT JOIN (SELECT addressable_id, string_agg(#{addresses_tbl}.full_name, '!!SEP!!') AS buyer_name FROM #{addresses_tbl} WHERE #{addresses_tbl}.category = 'billing' AND #{addresses_tbl}.addressable_type = 'Effective::Order' GROUP BY #{addresses_tbl}.addressable_id) #{addresses_tbl} ON orders.id = #{addresses_tbl}.addressable_id")
65
- .group("#{addresses_tbl}.buyer_name")
66
- .select("#{addresses_tbl}.buyer_name AS buyer_name")
67
- end
52
+ collection do
53
+ collection = Effective::OrderItem.unscoped
54
+ .joins(order: :user)
55
+ .select('order_items.*, orders.*, users.email AS email')
56
+ .select("#{query_subtotal} AS subtotal, #{query_tax} AS tax, #{query_total} AS total")
57
+ .group('order_items.id, orders.id, users.email')
68
58
 
69
- attributes[:user_id].present? ? collection.where("#{EffectiveOrders.orders_table_name.to_s}.user_id = ?", attributes[:user_id]) : collection
70
- end
59
+ if EffectiveOrders.require_billing_address && defined?(EffectiveAddresses)
60
+ addresses_tbl = EffectiveAddresses.addresses_table_name
71
61
 
72
- def query_subtotal
73
- 'SUM(price * quantity)'
62
+ collection = collection
63
+ .joins("LEFT JOIN (SELECT addressable_id, string_agg(#{addresses_tbl}.full_name, '!!SEP!!') AS buyer_name FROM #{addresses_tbl} WHERE #{addresses_tbl}.category = 'billing' AND #{addresses_tbl}.addressable_type = 'Effective::Order' GROUP BY #{addresses_tbl}.addressable_id) #{addresses_tbl} ON orders.id = #{addresses_tbl}.addressable_id")
64
+ .group("#{addresses_tbl}.buyer_name")
65
+ .select("#{addresses_tbl}.buyer_name AS buyer_name")
74
66
  end
75
67
 
76
- def query_total
77
- 'SUM((price * quantity) + (CASE tax_exempt WHEN true THEN 0 ELSE ((price * quantity) * tax_rate) END))'
78
- end
68
+ attributes[:user_id].present? ? collection.where("#{EffectiveOrders.orders_table_name.to_s}.user_id = ?", attributes[:user_id]) : collection
69
+ end
79
70
 
80
- def query_tax
81
- '(CASE tax_exempt WHEN true THEN 0 ELSE ((price * quantity) * tax_rate) END)'
82
- end
71
+ def query_subtotal
72
+ 'SUM(price * quantity)'
73
+ end
83
74
 
84
- # def search_column(collection, table_column, search_term)
85
- # if table_column[:name] == 'order'
86
- # collection.where("#{EffectiveOrders.order_items_table_name.to_s}.order_id = ?", Effective::Order.deobfuscate(search_term))
87
- # elsif table_column[:name] == 'purchase_state' && search_term == 'abandoned'
88
- # collection.where("#{EffectiveOrders.orders_table_name.to_s}.purchase_state IS NULL")
89
- # elsif table_column[:name] == 'subtotal'
90
- # collection.having("#{query_subtotal} = ?", (search_term.gsub(/[^0-9.]/, '').to_f * 100.0).to_i)
91
- # elsif table_column[:name] == 'tax'
92
- # collection.having("#{query_tax} = ?", (search_term.gsub(/[^0-9.]/, '').to_f * 100.0).to_i)
93
- # elsif table_column[:name] == 'total'
94
- # collection.having("#{query_total} = ?", (search_term.gsub(/[^0-9.]/, '').to_f * 100.0).to_i)
95
- # else
96
- # super
97
- # end
98
- # end
75
+ def query_total
76
+ 'SUM((price * quantity) + (CASE tax_exempt WHEN true THEN 0 ELSE ((price * quantity) * tax_rate) END))'
77
+ end
99
78
 
79
+ def query_tax
80
+ '(CASE tax_exempt WHEN true THEN 0 ELSE ((price * quantity) * tax_rate) END)'
100
81
  end
82
+
83
+ # def search_column(collection, table_column, search_term)
84
+ # if table_column[:name] == 'order'
85
+ # collection.where("#{EffectiveOrders.order_items_table_name.to_s}.order_id = ?", Effective::Order.deobfuscate(search_term))
86
+ # elsif table_column[:name] == 'purchase_state' && search_term == 'abandoned'
87
+ # collection.where("#{EffectiveOrders.orders_table_name.to_s}.purchase_state IS NULL")
88
+ # elsif table_column[:name] == 'subtotal'
89
+ # collection.having("#{query_subtotal} = ?", (search_term.gsub(/[^0-9.]/, '').to_f * 100.0).to_i)
90
+ # elsif table_column[:name] == 'tax'
91
+ # collection.having("#{query_tax} = ?", (search_term.gsub(/[^0-9.]/, '').to_f * 100.0).to_i)
92
+ # elsif table_column[:name] == 'total'
93
+ # collection.having("#{query_total} = ?", (search_term.gsub(/[^0-9.]/, '').to_f * 100.0).to_i)
94
+ # else
95
+ # super
96
+ # end
97
+ # end
98
+
101
99
  end
@@ -1,81 +1,91 @@
1
- unless Gem::Version.new(EffectiveDatatables::VERSION) < Gem::Version.new('3.0')
2
- class EffectiveOrdersDatatable < Effective::Datatable
3
- datatable do
4
- order :created_at, :desc
1
+ class EffectiveOrdersDatatable < Effective::Datatable
2
+ bulk_actions do
3
+ if EffectiveOrders.authorized?(view.controller, :admin, :effective_orders)
4
+ bulk_action(
5
+ 'Send payment request email to selected pending orders',
6
+ effective_orders.bulk_send_payment_request_admin_orders_path,
7
+ data: { confirm: 'Send payment request emails to pending orders?' }
8
+ )
9
+ end
5
10
 
6
- col :purchased_at
11
+ bulk_action(
12
+ 'Send receipt email to selected purchased orders',
13
+ effective_orders.bulk_send_buyer_receipt_orders_path,
14
+ data: { confirm: 'Send receipt emails to purchased orders?' }
15
+ )
16
+ end
7
17
 
8
- col :id
18
+ datatable do
19
+ order :created_at, :desc
9
20
 
10
- if attributes[:user_id].blank?
11
- col :user, label: 'Buyer', search: :string, sort: :email do |order|
12
- link_to order.user.email, (edit_admin_user_path(order.user) rescue admin_user_path(order.user) rescue '#')
13
- end
21
+ bulk_actions_col
14
22
 
15
- if EffectiveOrders.require_billing_address && EffectiveOrders.use_address_full_name
16
- val :buyer_name, visible: false do |order|
17
- order.billing_address.try(:full_name)
18
- end
19
- else
20
- val :buyer_name, visible: false do |order|
21
- order.user.to_s
22
- end
23
- end
24
- end
23
+ col :purchased_at
25
24
 
26
- if EffectiveOrders.require_billing_address
27
- col :billing_address
28
- end
25
+ col :id
29
26
 
30
- if EffectiveOrders.require_shipping_address
31
- col :shipping_address
27
+ if attributes[:user_id].blank?
28
+ col :user, label: 'Buyer', search: :string, sort: :email do |order|
29
+ link_to order.user.email, (edit_admin_user_path(order.user) rescue admin_user_path(order.user) rescue '#')
32
30
  end
33
31
 
34
- col :purchase_state, label: 'State', search: { collection: purchase_state_filter_values } do |order|
35
- order.purchase_state || EffectiveOrders::ABANDONED
32
+ if EffectiveOrders.require_billing_address && EffectiveOrders.use_address_full_name
33
+ val :buyer_name, visible: false do |order|
34
+ order.billing_address.try(:full_name)
35
+ end
36
+ else
37
+ val :buyer_name, visible: false do |order|
38
+ order.user.to_s
39
+ end
36
40
  end
41
+ end
42
+
43
+ if EffectiveOrders.require_billing_address
44
+ col :billing_address
45
+ end
37
46
 
38
- col :order_items
47
+ if EffectiveOrders.require_shipping_address
48
+ col :shipping_address
49
+ end
39
50
 
40
- col :subtotal, as: :price
41
- col :tax, as: :price
51
+ col :purchase_state, label: 'State', search: { collection: EffectiveOrders::PURCHASE_STATES.invert } do |order|
52
+ EffectiveOrders::PURCHASE_STATES[order.purchase_state]
53
+ end
42
54
 
43
- col :tax_rate, visible: false do |order|
44
- tax_rate_to_percentage(order.tax_rate)
45
- end
55
+ col :order_items, search: { as: :string }
46
56
 
47
- col :total, as: :price
57
+ col :subtotal, as: :price
58
+ col :tax, as: :price
48
59
 
49
- col :payment_provider, label: 'Provider', visible: false, search: { collection: ['nil'] + (EffectiveOrders.payment_providers + EffectiveOrders.other_payment_providers).sort }
50
- col :payment_card, label: 'Card'
60
+ col :tax_rate, visible: false do |order|
61
+ tax_rate_to_percentage(order.tax_rate)
62
+ end
51
63
 
52
- col :note, visible: false
53
- col :note_to_buyer, visible: false
54
- col :note_internal, visible: false
64
+ col :total, as: :price
55
65
 
56
- col :created_at, visible: false
57
- col :updated_at, visible: false
66
+ col :payment_provider, label: 'Provider', visible: false, search: { collection: ['nil'] + (EffectiveOrders.payment_providers + EffectiveOrders.other_payment_providers).sort }
67
+ col :payment_card, label: 'Card'
58
68
 
59
- actions_col partial: 'admin/orders/actions', partial_as: :order
60
- end
69
+ col :note, visible: false
70
+ col :note_to_buyer, visible: false
71
+ col :note_internal, visible: false
61
72
 
62
- collection do
63
- scope = Effective::Order.unscoped.includes(:addresses, :order_items, :user)
73
+ col :created_at, visible: false
74
+ col :updated_at, visible: false
64
75
 
65
- if EffectiveOrders.orders_collection_scope.respond_to?(:call)
66
- scope = EffectiveOrders.orders_collection_scope.call(scope)
67
- end
76
+ actions_col partial: 'admin/orders/actions', partial_as: :order
68
77
 
69
- attributes[:user_id].present? ? scope.where(user_id: attributes[:user_id]) : scope
70
- end
78
+ aggregate :total
79
+ end
80
+
81
+ collection do
82
+ scope = Effective::Order.unscoped.includes(:addresses, :order_items, :user)
71
83
 
72
- def purchase_state_filter_values
73
- [
74
- [EffectiveOrders::ABANDONED, nil],
75
- [EffectiveOrders::PURCHASED, EffectiveOrders::PURCHASED],
76
- [EffectiveOrders::DECLINED, EffectiveOrders::DECLINED],
77
- [EffectiveOrders::PENDING, EffectiveOrders::PENDING]
78
- ]
84
+ if EffectiveOrders.orders_collection_scope.respond_to?(:call)
85
+ scope = EffectiveOrders.orders_collection_scope.call(scope)
79
86
  end
87
+
88
+ attributes[:user_id].present? ? scope.where(user_id: attributes[:user_id]) : scope
80
89
  end
90
+
81
91
  end
@@ -1,24 +1,27 @@
1
1
  module EffectiveCartsHelper
2
+ # TODO: Consider unique
2
3
  def current_cart(for_user = nil)
3
4
  @cart ||= (
4
5
  user = for_user || (current_user rescue nil) # rescue protects me against Devise not being installed
5
6
 
6
7
  if user.present?
7
- Effective::Cart.where(user_id: user.id).first_or_create.tap do |user_cart|
8
- if session[:cart].present?
9
- session_cart = Effective::Cart.where('user_id IS NULL').where(id: session[:cart]).first
8
+ user_cart = Effective::Cart.where(user: user).first_or_create
10
9
 
11
- if session_cart.present?
12
- session_cart.cart_items.update_all(cart_id: user_cart.id)
13
- session_cart.destroy
14
- user_cart.reload
15
- end
10
+ # Merge session cart into user cart.
11
+ if session[:cart].present?
12
+ session_cart = Effective::Cart.where(user: nil).where(id: session[:cart]).first
16
13
 
17
- session[:cart] = nil
14
+ if session_cart
15
+ session_cart.cart_items.each { |i| user_cart.add(i.purchasable, quantity: i.quantity, unique: i.unique) }
16
+ session_cart.destroy
18
17
  end
18
+
19
+ session[:cart] = nil
19
20
  end
21
+
22
+ user_cart
20
23
  elsif session[:cart].present?
21
- Effective::Cart.where('user_id IS NULL').where(id: session[:cart]).first_or_create
24
+ Effective::Cart.where(user_id: nil).where(id: session[:cart]).first_or_create
22
25
  else
23
26
  cart = Effective::Cart.create!
24
27
  session[:cart] = cart.id
@@ -42,7 +45,7 @@ module EffectiveCartsHelper
42
45
  end
43
46
 
44
47
  def link_to_add_to_cart(purchasable, opts = {})
45
- raise ArgumentError.new('expecting an acts_as_purchasable object') unless purchasable.kind_of?(ActsAsPurchasable)
48
+ raise 'expecting an acts_as_purchasable object' unless purchasable.kind_of?(ActsAsPurchasable)
46
49
 
47
50
  options = {
48
51
  label: 'Add to Cart',
@@ -60,7 +63,7 @@ module EffectiveCartsHelper
60
63
  end
61
64
 
62
65
  def link_to_remove_from_cart(cart_item, opts = {})
63
- raise ArgumentError.new('expecting an Effective::CartItem object') unless cart_item.kind_of?(Effective::CartItem)
66
+ raise 'expecting an Effective::CartItem object' unless cart_item.kind_of?(Effective::CartItem)
64
67
 
65
68
  options = {
66
69
  label: 'Remove',
@@ -120,11 +123,11 @@ module EffectiveCartsHelper
120
123
 
121
124
  def render_cart(cart = nil)
122
125
  cart ||= current_cart
123
- render(partial: 'effective/carts/cart', locals: {cart: cart})
126
+ render(partial: 'effective/carts/cart', locals: { cart: cart })
124
127
  end
125
128
 
126
129
  def render_purchasables(*purchasables)
127
- render(partial: 'effective/orders/order_items', locals: {order: Effective::Order.new(purchasables)})
130
+ render(partial: 'effective/orders/order_items', locals: { order: Effective::Order.new(purchasables) })
128
131
  end
129
132
 
130
133
  end