camaleon_ecommerce 1.2.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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/plugins/ecommerce/switch.png +0 -0
  3. data/app/assets/javascripts/plugins/ecommerce/admin_product.js.coffee +1 -1
  4. data/app/assets/javascripts/plugins/ecommerce/admin_settings.js +16 -0
  5. data/app/assets/javascripts/plugins/ecommerce/cart.js +1 -0
  6. data/app/assets/javascripts/plugins/ecommerce/jquery.multi-select.js +535 -0
  7. data/app/assets/stylesheets/plugins/ecommerce/multi-select.css.scss +94 -0
  8. data/app/controllers/plugins/ecommerce/admin/orders_controller.rb +37 -20
  9. data/app/controllers/plugins/ecommerce/admin/settings_controller.rb +2 -2
  10. data/app/controllers/plugins/ecommerce/front/checkout_controller.rb +16 -15
  11. data/app/decorators/plugins/ecommerce/cart_decorator.rb +19 -0
  12. data/app/decorators/plugins/ecommerce/order_decorator.rb +70 -0
  13. data/app/decorators/plugins/ecommerce/product_decorator.rb +16 -9
  14. data/app/decorators/plugins/ecommerce/product_item_decorator.rb +5 -1
  15. data/app/helpers/plugins/ecommerce/ecommerce_email_helper.rb +60 -59
  16. data/app/helpers/plugins/ecommerce/ecommerce_functions_helper.rb +5 -10
  17. data/app/helpers/plugins/ecommerce/ecommerce_helper.rb +12 -3
  18. data/app/models/plugins/ecommerce/cart.rb +3 -25
  19. data/app/models/plugins/ecommerce/order.rb +0 -21
  20. data/app/models/plugins/ecommerce/payment_method.rb +4 -0
  21. data/app/models/plugins/ecommerce/shipping_method.rb +4 -1
  22. data/app/services/plugins/ecommerce/cart_service.rb +0 -9
  23. data/app/views/plugins/ecommerce/admin/orders/index.html.erb +47 -51
  24. data/app/views/plugins/ecommerce/admin/orders/show.html.erb +1 -1
  25. data/app/views/plugins/ecommerce/admin/payment_methods/form.html.erb +2 -6
  26. data/app/views/plugins/ecommerce/admin/payment_methods/index.html.erb +4 -6
  27. data/app/views/plugins/ecommerce/admin/settings/index.html.erb +60 -20
  28. data/app/views/plugins/ecommerce/admin/shipping_methods/form.html.erb +1 -5
  29. data/app/views/plugins/ecommerce/admin/shipping_methods/index.html.erb +2 -4
  30. data/app/views/plugins/ecommerce/front/checkout/cart_index.html.erb +2 -2
  31. data/app/views/plugins/ecommerce/front/checkout/index.html.erb +1 -1
  32. data/app/views/plugins/ecommerce/front/login.html.erb +1 -1
  33. data/app/views/plugins/ecommerce/front/orders/index.html.erb +2 -2
  34. data/app/views/plugins/ecommerce/front/orders/show.html.erb +13 -14
  35. data/app/views/plugins/ecommerce/partials/checkout/_details.html.erb +1 -1
  36. data/app/views/plugins/ecommerce/partials/checkout/_payments.html.erb +116 -110
  37. data/app/views/plugins/ecommerce/partials/checkout/_products_detail.html.erb +5 -2
  38. data/app/views/plugins/ecommerce/partials/checkout/_user_info.html.erb +0 -1
  39. data/app/views/plugins/ecommerce/partials/email/_billing_address.html.erb +11 -0
  40. data/app/views/plugins/ecommerce/partials/email/_product_table.html.erb +46 -0
  41. data/app/views/plugins/ecommerce/partials/email/_shipping_address.html.erb +11 -0
  42. data/app/views/{plugins/ecommerce/partials → post_types/commerce}/_cart_widget.html.erb +0 -0
  43. data/app/views/post_types/commerce/_product_info.html.erb +30 -32
  44. data/app/views/post_types/commerce/single.html.erb +9 -13
  45. data/config/camaleon_plugin.json +2 -1
  46. data/config/custom_models.rb +43 -0
  47. data/config/locales/en.yml +0 -1
  48. data/config/locales/es.yml +69 -7
  49. data/config/routes.rb +1 -0
  50. data/db/migrate/20161213222142_add_invoice_number.rb +6 -0
  51. data/db/migrate/20161214224919_remove_ecommerce_stock_field.rb +7 -0
  52. data/lib/ecommerce/engine.rb +4 -2
  53. data/lib/ecommerce/version.rb +1 -1
  54. metadata +58 -15
  55. data/app/assets/javascripts/plugins/ecommerce/jquery.creditCardValidator.js +0 -208
  56. data/app/services/plugins/ecommerce/order_service.rb +0 -26
  57. data/app/views/camaleon_cms/html_mailer/order_canceled.html.erb +0 -2
  58. data/app/views/camaleon_cms/html_mailer/order_confirmed.html.erb +0 -2
  59. data/app/views/camaleon_cms/html_mailer/order_received.html.erb +0 -5
  60. data/app/views/camaleon_cms/html_mailer/order_received_admin.html.erb +0 -3
  61. data/app/views/camaleon_cms/html_mailer/order_shipped.html.erb +0 -2
  62. data/app/views/camaleon_cms/html_mailer/recovery_cart.html.erb +0 -4
@@ -0,0 +1,94 @@
1
+ .ms-container{
2
+ //background: transparent asset-plugin-url('switch.png') no-repeat 50% 50%;
3
+ background: transparent asset-plugin-url('switch.png') no-repeat 50% 50%;
4
+ width: 370px;
5
+ }
6
+
7
+ .ms-container:after{
8
+ content: ".";
9
+ display: block;
10
+ height: 0;
11
+ line-height: 0;
12
+ font-size: 0;
13
+ clear: both;
14
+ min-height: 0;
15
+ visibility: hidden;
16
+ }
17
+
18
+ .ms-container .ms-selectable, .ms-container .ms-selection{
19
+ background: #fff;
20
+ color: #555555;
21
+ float: left;
22
+ width: 45%;
23
+ }
24
+ .ms-container .ms-selection{
25
+ float: right;
26
+ }
27
+
28
+ .ms-container .ms-list{
29
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
30
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
31
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
32
+ -webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
33
+ -moz-transition: border linear 0.2s, box-shadow linear 0.2s;
34
+ -ms-transition: border linear 0.2s, box-shadow linear 0.2s;
35
+ -o-transition: border linear 0.2s, box-shadow linear 0.2s;
36
+ transition: border linear 0.2s, box-shadow linear 0.2s;
37
+ border: 1px solid #ccc;
38
+ -webkit-border-radius: 3px;
39
+ -moz-border-radius: 3px;
40
+ border-radius: 3px;
41
+ position: relative;
42
+ height: 200px;
43
+ padding: 0;
44
+ overflow-y: auto;
45
+ }
46
+
47
+ .ms-container .ms-list.ms-focus{
48
+ border-color: rgba(82, 168, 236, 0.8);
49
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
50
+ -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
51
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
52
+ outline: 0;
53
+ outline: thin dotted \9;
54
+ }
55
+
56
+ .ms-container ul{
57
+ margin: 0;
58
+ list-style-type: none;
59
+ padding: 0;
60
+ }
61
+
62
+ .ms-container .ms-optgroup-container{
63
+ width: 100%;
64
+ }
65
+
66
+ .ms-container .ms-optgroup-label{
67
+ margin: 0;
68
+ padding: 5px 0px 0px 5px;
69
+ cursor: pointer;
70
+ color: #999;
71
+ }
72
+
73
+ .ms-container .ms-selectable li.ms-elem-selectable,
74
+ .ms-container .ms-selection li.ms-elem-selection{
75
+ border-bottom: 1px #eee solid;
76
+ padding: 2px 10px;
77
+ color: #555;
78
+ font-size: 14px;
79
+ }
80
+
81
+ .ms-container .ms-selectable li.ms-hover,
82
+ .ms-container .ms-selection li.ms-hover{
83
+ cursor: pointer;
84
+ color: #fff;
85
+ text-decoration: none;
86
+ background-color: #08c;
87
+ }
88
+
89
+ .ms-container .ms-selectable li.disabled,
90
+ .ms-container .ms-selection li.disabled{
91
+ background-color: #eee;
92
+ color: #aaa;
93
+ cursor: text;
94
+ }
@@ -3,21 +3,8 @@ class Plugins::Ecommerce::Admin::OrdersController < Plugins::Ecommerce::AdminCon
3
3
  before_action :set_order_bread
4
4
 
5
5
  def index
6
- orders = current_site.orders
7
- if params[:q].present?
8
- orders = orders.where("#{Plugins::Ecommerce::Order.table_name}.slug LIKE ?", "%#{params[:q]}%")
9
- end
10
- if params[:c].present?
11
- orders = orders.joins(:user).where("#{Cama::User.table_name}.first_name LIKE ? OR #{Cama::User.table_name}.last_name LIKE ?", "%#{params[:c]}%", "%#{params[:c]}%")
12
- end
13
- if params[:e].present?
14
- orders = orders.joins(:user).where("#{Cama::User.table_name}.email LIKE ?", "%#{params[:e]}%")
15
- end
16
- if params[:s].present?
17
- orders = orders.where(status: params[:s].split('|'))
18
- end
19
- orders = orders.order('received_at desc')
20
- @orders = orders.paginate(:page => params[:page], :per_page => current_site.admin_per_page)
6
+ @q = current_site.orders.order('received_at desc').ransack(params[:q])
7
+ @orders = @q.result.paginate(:page => params[:page], :per_page => current_site.admin_per_page)
21
8
  end
22
9
 
23
10
  def show
@@ -36,20 +23,24 @@ class Plugins::Ecommerce::Admin::OrdersController < Plugins::Ecommerce::AdminCon
36
23
  end
37
24
 
38
25
  def update
26
+ hooks_run('plugin_ecommerce_before_update_order', @order)
39
27
  @order.set_meta("billing_address", params[:order][:billing_address])
40
28
  @order.set_meta("shipping_address", params[:order][:shipping_address])
41
29
  @order.set_metas(params[:metas])
42
30
  @order.update(params.require(:plugins_ecommerce_order).permit(:shipped_at))
31
+ hooks_run('plugin_ecommerce_after_destroy_order', @order)
43
32
  flash[:notice] = "#{t('plugins.ecommerce.message.order_updated', default: 'Order Updated')}"
44
33
  redirect_to action: :show, id: params[:id]
45
34
  end
46
35
 
47
36
  def destroy
37
+ hooks_run('plugin_ecommerce_before_destroy_order', @order)
48
38
  if @order.destroy
49
39
  flash[:notice] = "#{t('plugins.ecommerce.message.order_destroyed', default: 'Order Destroyed')}"
50
40
  else
51
41
  flash[:error] = "#{t('plugins.ecommerce.message.order_no_destroyed', default: 'Occurred some problems destroying the order')}"
52
42
  end
43
+ hooks_run('plugin_ecommerce_after_destroy_order', @order)
53
44
  redirect_to action: :index
54
45
  end
55
46
 
@@ -57,6 +48,7 @@ class Plugins::Ecommerce::Admin::OrdersController < Plugins::Ecommerce::AdminCon
57
48
  def mark_accepted
58
49
  r = {order: @order}; hooks_run('plugin_ecommerce_before_accepted_order', r)
59
50
  @order.accepted!
51
+ commerce_order_send_mail(@order, 'email_order_accepted')
60
52
  message = "#{t('plugins.ecommerce.message.order_accepted', default: 'Order Accepted')}"
61
53
  r = {order: @order, message: message}; hooks_run('plugin_ecommerce_after_accepted_order', r)
62
54
  flash[:notice] = r[:message]
@@ -65,36 +57,61 @@ class Plugins::Ecommerce::Admin::OrdersController < Plugins::Ecommerce::AdminCon
65
57
 
66
58
  def mark_bank_confirmed
67
59
  if @order.on_delivery_pending?
60
+ hooks_run('plugin_ecommerce_before_on_delivery_order', @order)
68
61
  @order.on_delivery_confirmed!
62
+ commerce_order_send_mail(@order, 'email_order_confirmed_on_delivery')
69
63
  flash[:notice] = "#{t('plugins.ecommerce.message.order_on_delivery_confirmed', default: 'Payment on Delivery Confirmed')}"
70
- commerce_send_order_received_email(@order)
64
+ hooks_run('plugin_ecommerce_after_on_delivery_order', @order)
71
65
  else
66
+ hooks_run('plugin_ecommerce_before_bank_confirm_order', @order)
72
67
  @order.bank_confirmed!
68
+ commerce_order_send_mail(@order, 'email_order_confirmed_bank')
73
69
  flash[:notice] = "#{t('plugins.ecommerce.message.order_bank_confirmed', default: 'Pay Bank Confirmed')}"
74
- commerce_send_order_received_email(@order, true)
70
+ hooks_run('plugin_ecommerce_after_bank_confirm_order', @order)
75
71
  end
76
72
  redirect_to action: :index
77
73
  end
78
74
 
79
75
  # shipped order
80
76
  def mark_shipped
77
+ hooks_run('plugin_ecommerce_before_shipped_order', @order)
81
78
  @order.shipped!(params[:consignment_number])
82
- cama_send_email(@order.user.email, t('plugins.ecommerce.mail.order_shipped.subject'), {template_name: 'order_shipped', extra_data: {order: @order, consignment_number: params[:consignment_number]}})
79
+ commerce_order_send_mail(@order, 'email_order_shipped')
83
80
  flash[:notice] = "#{t('plugins.ecommerce.message.order_shipped', default: 'Order Shipped')}"
81
+ hooks_run('plugin_ecommerce_after_shipped_order', @order)
84
82
  redirect_to action: :index
85
83
  end
86
84
 
87
85
  def mark_canceled
86
+ hooks_run('plugin_ecommerce_before_canceled_order', @order)
88
87
  @order.canceled!
89
88
  @order.set_meta('description', params[:description])
90
- cama_send_email(@order.user.email, t('plugins.ecommerce.mail.order_canceled.subject'), {template_name: 'order_canceled', extra_data: {order: @order}, description: params[:description]})
89
+ commerce_order_send_mail(@order, 'email_order_cancelled')
91
90
  flash[:notice] = "#{t('plugins.ecommerce.message.order_canceled', default: 'Order canceled')}"
91
+ hooks_run('plugin_ecommerce_after_canceled_order', @order)
92
+ redirect_to action: :index
93
+ end
94
+
95
+ def resend_email
96
+ case @order.status
97
+ when 'paid', 'bank_pending', 'on_delivery'
98
+ commerce_order_send_mail(@order)
99
+ when 'shipped'
100
+ commerce_order_send_mail(@order, 'email_order_shipped')
101
+ when 'canceled'
102
+ commerce_order_send_mail(@order, 'email_order_cancelled')
103
+ else
104
+ flash[:error] = "#{t('plugins.ecommerce.message.unknown_status', default: 'Unknown Status')}"
105
+ redirect_to action: :index
106
+ return
107
+ end
108
+ flash[:notice] = "#{t('plugins.ecommerce.message.order_email_resent', default: 'Order Email Resent')}"
92
109
  redirect_to action: :index
93
110
  end
94
111
 
95
112
  private
96
113
  def set_order
97
- @order = current_site.orders.find_by_slug(params[:id] || params[:order_id])
114
+ @order = current_site.orders.find_by_slug(params[:id] || params[:order_id]).decorate
98
115
  end
99
116
 
100
117
  def set_order_bread
@@ -1,12 +1,12 @@
1
1
  class Plugins::Ecommerce::Admin::SettingsController < Plugins::Ecommerce::AdminController
2
2
  add_breadcrumb I18n.t("plugins.ecommerce.e_commerce")
3
3
  def index
4
- @setting = current_site.get_meta("_setting_ecommerce", {})
4
+ @setting = current_site.e_settings
5
5
  end
6
6
 
7
7
  # save settings
8
8
  def saved
9
- current_site.set_meta('_setting_ecommerce', params[:setting])
9
+ current_site.e_settings(params[:setting])
10
10
  flash[:notice] = t('camaleon_cms.admin.post_type.message.updated')
11
11
  redirect_to action: :index
12
12
  end
@@ -34,8 +34,10 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
34
34
  flash[:cama_ecommerce][:error] = errors.join('<br>')
35
35
  redirect_to :back
36
36
  else
37
+ hooks_run('plugin_ecommerce_before_complete_free_order', @cart)
37
38
  @cart.set_meta('free_order', true)
38
- mark_order_like_received(@cart)
39
+ commerce_mark_cart_received(@cart)
40
+ hooks_run('plugin_ecommerce_after_complete_free_order', @cart)
39
41
  redirect_to plugins_ecommerce_orders_path
40
42
  end
41
43
  else
@@ -67,16 +69,16 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
67
69
  product = current_site.products.find(data[:product_id]).decorate
68
70
  unless product.valid_variation?(params[:variation_id])
69
71
  flash[:cama_ecommerce][:error] = t('plugins.ecommerce.messages.missing_variation', default: 'Invalid Product Variation')
70
- return redirect_to action: :cart_index
72
+ return params[:format] == 'json' ? render(json: flash.discard(:cama_ecommerce).to_hash) : (redirect_to action: :cart_index)
71
73
  end
72
74
 
73
75
  unless product.can_added?(qty, params[:variation_id])
74
- flash[:cama_ecommerce][:error] = t('plugins.ecommerce.messages.not_enough_product_qty', product: product.the_variation_title(params[:variation_id]), qty: product.the_qty_real(params[:variation_id]), default: 'There is not enough products "%{product}" (Available %{qty})')
75
- return redirect_to :back
76
+ flash[:cama_ecommerce][:error] = t('plugins.ecommerce.messages.not_enough_product_qty', product: product.the_variation_title(params[:variation_id]), qty: product.the_qty(params[:variation_id]), default: 'There is not enough products "%{product}" (Available %{qty})')
77
+ return params[:format] == 'json' ? render(json: flash.discard(:cama_ecommerce).to_hash) : (redirect_to :back)
76
78
  end
77
79
  @cart.add_product(product, qty, params[:variation_id])
78
80
  flash[:cama_ecommerce][:notice] = t('plugins.ecommerce.messages.added_product_in_cart', default: 'Product added into cart')
79
- redirect_to action: :cart_index
81
+ params[:format] == 'json' ? render(json: flash.discard(:cama_ecommerce).to_hash) : (redirect_to action: :cart_index)
80
82
  end
81
83
 
82
84
  def cart_update
@@ -88,24 +90,24 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
88
90
  if product.can_added?(qty, item.variation_id)
89
91
  @cart.add_product(product, qty, item.variation_id)
90
92
  else
91
- errors << t('plugins.ecommerce.messages.not_enough_product_qty', product: product.the_variation_title(item.variation_id), qty: product.the_qty_real(item.variation_id), default: 'There is not enough products "%{product}" (Available %{qty})')
93
+ errors << t('plugins.ecommerce.messages.not_enough_product_qty', product: product.the_variation_title(item.variation_id), qty: product.the_qty(item.variation_id), default: 'There is not enough products "%{product}" (Available %{qty})')
92
94
  end
93
95
  end
94
96
  flash[:cama_ecommerce][:error] = errors.join('<br>') if errors.present?
95
97
  flash[:cama_ecommerce][:notice] = t('plugins.ecommerce.messages.cart_updated', default: 'Shopping cart updated') unless errors.present?
96
- redirect_to action: :cart_index
98
+ params[:format] == 'json' ? render(json: flash.discard(:cama_ecommerce).to_hash) : (redirect_to action: :cart_index)
97
99
  end
98
100
 
99
101
  def cart_remove
100
102
  @cart.product_items.find(params[:product_item_id]).destroy
101
103
  flash[:cama_ecommerce][:notice] = t('plugins.ecommerce.messages.cart_deleted', default: 'Product removed from your shopping cart')
102
- redirect_to action: :cart_index
104
+ params[:format] == 'json' ? render(json: flash.discard(:cama_ecommerce).to_hash) : (redirect_to action: :cart_index)
103
105
  end
104
106
 
105
107
  def cancel_order
106
108
  @cart.update({status: 'canceled', kind: 'order', closed_at: Time.now})
107
109
  flash[:cama_ecommerce][:notice] = t('plugins.ecommerce.messages.canceled_order', default: "Canceled Order")
108
- redirect_to plugins_ecommerce_orders_url
110
+ params[:format] == 'json' ? render(json: flash.discard(:cama_ecommerce).to_hash) : (redirect_to plugins_ecommerce_orders_url)
109
111
  end
110
112
 
111
113
  def pay_by_stripe
@@ -121,20 +123,20 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
121
123
  end
122
124
  redirect_to :back
123
125
  else
124
- mark_order_like_received(@cart)
126
+ commerce_mark_cart_received(@cart)
125
127
  redirect_to plugins_ecommerce_orders_url
126
128
  end
127
129
  end
128
130
 
129
131
  def pay_by_bank_transfer
130
132
  @cart.set_meta("payment_data", params[:details])
131
- mark_order_like_received(@cart, 'bank_pending')
133
+ commerce_mark_cart_received(@cart, 'bank_pending')
132
134
  redirect_to plugins_ecommerce_orders_url
133
135
  end
134
136
 
135
137
  def pay_by_on_delivery
136
138
  @cart.set_meta("payment_data", params[:details])
137
- mark_order_like_received(@cart, 'on_delivery')
139
+ commerce_mark_cart_received(@cart, 'on_delivery')
138
140
  redirect_to plugins_ecommerce_orders_url
139
141
  end
140
142
 
@@ -153,7 +155,7 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
153
155
  flash[:payment_error] = true
154
156
  redirect_to :back
155
157
  else
156
- mark_order_like_received(@cart)
158
+ commerce_mark_cart_received(@cart)
157
159
  redirect_to plugins_ecommerce_orders_url
158
160
  end
159
161
  end
@@ -167,7 +169,7 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
167
169
 
168
170
  if response.success?
169
171
  @cart.set_meta('payment_data', {token: params[:token], PayerID: params[:PayerID], ip: request.remote_ip})
170
- mark_order_like_received(@cart)
172
+ commerce_mark_cart_received(@cart)
171
173
  else
172
174
  flash[:cama_ecommerce][:error] = response.message
173
175
  end
@@ -175,7 +177,6 @@ class Plugins::Ecommerce::Front::CheckoutController < Plugins::Ecommerce::FrontC
175
177
  end
176
178
 
177
179
  def cancel_paypal
178
- # @cart = current_site.orders.find_by_slug(params[:order])
179
180
  redirect_to plugins_ecommerce_orders_url
180
181
  end
181
182
 
@@ -24,4 +24,23 @@ class Plugins::Ecommerce::CartDecorator < Draper::Decorator
24
24
  def the_total_shipping
25
25
  h.e_parse_price(object.total_shipping)
26
26
  end
27
+
28
+ # return the product titles in array format
29
+ def products_title
30
+ object.product_items.map{|i| p=i.product.decorate; p.the_variation_title(i.variation_id) }.join(', ')
31
+ end
32
+
33
+ # convert the cart into order with specific status
34
+ def convert_to_order(status = 'paid')
35
+ prepare_to_pay
36
+ update_amounts
37
+ object.update_columns(
38
+ status: status,
39
+ kind: 'order',
40
+ received_at: Time.current
41
+ )
42
+ order = h.current_site.orders.find(object.id).decorate
43
+ order.paid! if status == 'paid'
44
+ order
45
+ end
27
46
  end
@@ -19,4 +19,74 @@ class Plugins::Ecommerce::OrderDecorator < Draper::Decorator
19
19
  _url = object.shipping_method.options[:url_tracking].gsub("{{consignment_number}}", consignment_number) rescue ''
20
20
  end
21
21
  end
22
+
23
+ # return created at date formatted
24
+ def the_created_at(format = :long)
25
+ h.l(object.created_at, format: format.to_sym)
26
+ end
27
+
28
+ def the_paid_at(format = :long)
29
+ h.l(object.paid_at, format: format.to_sym) rescue ''
30
+ end
31
+
32
+ def the_received_at(format = :long)
33
+ h.l(object.received_at, format: format.to_sym) rescue ''
34
+ end
35
+
36
+ def the_shipped_at(format = :long)
37
+ h.l(object.shipped_at, format: format.to_sym) rescue ''
38
+ end
39
+
40
+ # return shipping method title
41
+ def the_shipping_method
42
+ object.shipping_method.try(:decorate).try(:the_title)
43
+ end
44
+
45
+ # return the url of the current order
46
+ def the_url
47
+ h.plugins_ecommerce_order_show_path(order: object.slug)
48
+ end
49
+
50
+ # mark current order as paid and set a invoice number
51
+ def paid!
52
+ update_columns(invoice_number: get_invoice_number, status: 'paid', paid_at: Time.current)
53
+ end
54
+
55
+ def accepted!
56
+ update_columns({status: 'accepted', accepted_at: Time.current})
57
+ end
58
+
59
+ def shipped!(code)
60
+ update_columns({status: 'shipped', shipped_at: Time.current})
61
+ set_meta('consignment_number', code)
62
+ end
63
+
64
+ def canceled!
65
+ update_columns({status: 'canceled', closed_at: Time.current})
66
+ end
67
+
68
+ def bank_confirmed!
69
+ paid!
70
+ end
71
+
72
+ def on_delivery_confirmed!
73
+ paid!
74
+ end
75
+
76
+ # return the invoice pdf path
77
+ def the_invoice_path
78
+ folder = CamaleonCmsLocalUploader::private_file_path('invoices', h.current_site).to_s
79
+ FileUtils.mkdir_p(folder) unless Dir.exist?(folder)
80
+ File.join(folder, "#{object.invoice_number.presence || object.slug}.pdf").to_s
81
+ end
82
+
83
+ private
84
+ # return a new invoice number
85
+ def get_invoice_number
86
+ res = h.current_site.e_invoice_number_from
87
+ new_inv = res + 1
88
+ h.current_site.e_set_setting('invoice_number_from', new_inv)
89
+ h.cama_send_mail_to_admin(I18n.t('plugins.ecommerce.email.invoice_number_exceeded_subject', default: 'Invoice Number Exceeded.'), {content: I18n.t('plugins.ecommerce.email.invoice_number_exceeded_body', default: 'The Invoice Number %{number} was exceeded. Please review ecommerce settings.', number: new_inv)}) if new_inv >= h.current_site.e_invoice_number_to
90
+ res
91
+ end
22
92
  end
@@ -32,7 +32,7 @@ class Plugins::Ecommerce::ProductDecorator < CamaleonCms::PostDecorator
32
32
  if variation_id.present?
33
33
  get_variation(variation_id).qty || 0
34
34
  else
35
- is_variation_product? ? (get_default_variation.qty || 0) : object.get_field_value('ecommerce_qty').to_i || 0
35
+ is_variation_product? ? map_variations_the_qty.map{|k,v| v }.reduce(&:+) : (object.get_field_value('ecommerce_qty').to_i || 0)
36
36
  end
37
37
  end
38
38
 
@@ -46,15 +46,11 @@ class Plugins::Ecommerce::ProductDecorator < CamaleonCms::PostDecorator
46
46
  end
47
47
 
48
48
  def the_photos
49
- object.get_field_values('ecommerce_photos') || []
49
+ is_variation_product? ? object.product_variations.pluck(:photo) : object.get_field_values('ecommerce_photos') || []
50
50
  end
51
51
 
52
52
  def in_stock?(variation_id = nil)
53
- if variation_id.present?
54
- get_variation(variation_id).qty > 0
55
- else
56
- object.get_field_value('ecommerce_stock').to_s.to_bool
57
- end
53
+ the_qty(variation_id) > 0
58
54
  end
59
55
 
60
56
  def price(variation_id = nil)
@@ -92,7 +88,7 @@ class Plugins::Ecommerce::ProductDecorator < CamaleonCms::PostDecorator
92
88
  end
93
89
 
94
90
  def the_stock_status(variation_id = nil)
95
- if in_stock?(variation_id) && the_qty_real.to_i > 0
91
+ if in_stock?(variation_id)
96
92
  "<span class='label label-success'>#{I18n.t('plugins.ecommerce.product.in_stock')}</span>"
97
93
  else
98
94
  "<span class='label label-danger'>#{I18n.t('plugins.ecommerce.product.not_in_tock')}</span>"
@@ -113,7 +109,7 @@ class Plugins::Ecommerce::ProductDecorator < CamaleonCms::PostDecorator
113
109
 
114
110
  # check if there are enough products to be purchased
115
111
  def can_added?(qty, variation_id = nil)
116
- (the_qty_real(variation_id) - qty).to_i >= 0
112
+ (the_qty(variation_id) - qty).to_i >= 0
117
113
  end
118
114
 
119
115
  def self.object_class_name
@@ -136,6 +132,7 @@ class Plugins::Ecommerce::ProductDecorator < CamaleonCms::PostDecorator
136
132
  end
137
133
 
138
134
  # return (Hash) all variations qty for each variation, sample: {1: 10, 5: 2, 3: 0}
135
+ # note: this includes the quantity of items of user carts
139
136
  def map_variations_the_qty_real
140
137
  res = {}
141
138
  return res unless is_variation_product?
@@ -145,6 +142,16 @@ class Plugins::Ecommerce::ProductDecorator < CamaleonCms::PostDecorator
145
142
  res
146
143
  end
147
144
 
145
+ # return (Hash) all variations qty for each variation, sample: {1: 10, 5: 2, 3: 0}
146
+ def map_variations_the_qty
147
+ res = {}
148
+ return res unless is_variation_product?
149
+ object.product_variations.each do |var|
150
+ res[var.id] = var.qty
151
+ end
152
+ res
153
+ end
154
+
148
155
  # return the first variation of a product
149
156
  def get_default_variation
150
157
  @_cama_cache_get_default_variation ||= object.product_variations.first