camaleon_ecommerce 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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