camaleon_ecommerce 1.1 → 1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/plugins/ecommerce/admin_product.js.coffee +83 -0
- data/app/assets/javascripts/plugins/ecommerce/cart.js +3 -0
- data/app/controllers/plugins/ecommerce/admin/coupons_controller.rb +6 -12
- data/app/controllers/plugins/ecommerce/admin/orders_controller.rb +2 -8
- data/app/controllers/plugins/ecommerce/admin/payment_methods_controller.rb +7 -12
- data/app/controllers/plugins/ecommerce/admin/prices_controller.rb +0 -8
- data/app/controllers/plugins/ecommerce/admin/settings_controller.rb +0 -8
- data/app/controllers/plugins/ecommerce/admin/shipping_methods_controller.rb +6 -14
- data/app/controllers/plugins/ecommerce/admin/tax_rates_controller.rb +6 -12
- data/app/controllers/plugins/ecommerce/admin_controller.rb +27 -8
- data/app/controllers/plugins/ecommerce/front/checkout_controller.rb +42 -75
- data/app/controllers/plugins/ecommerce/front/orders_controller.rb +2 -10
- data/app/controllers/plugins/ecommerce/front_controller.rb +0 -8
- data/app/decorators/plugins/ecommerce/coupon_decorator.rb +0 -8
- data/app/decorators/plugins/ecommerce/product_decorator.rb +86 -35
- data/app/decorators/plugins/ecommerce/product_item_decorator.rb +27 -3
- data/app/decorators/plugins/ecommerce/product_variation_decorator.rb +18 -0
- data/app/helpers/plugins/ecommerce/ecommerce_email_helper.rb +11 -13
- data/app/helpers/plugins/ecommerce/ecommerce_functions_helper.rb +25 -11
- data/app/helpers/plugins/ecommerce/ecommerce_helper.rb +22 -27
- data/app/helpers/plugins/ecommerce/ecommerce_payment_helper.rb +1 -56
- data/app/models/plugins/ecommerce/attribute.rb +9 -0
- data/app/models/plugins/ecommerce/cart.rb +46 -28
- data/app/models/plugins/ecommerce/coupon.rb +0 -8
- data/app/models/plugins/ecommerce/legacy_cart.rb +50 -0
- data/app/models/plugins/ecommerce/legacy_order.rb +48 -0
- data/app/models/plugins/ecommerce/order.rb +0 -8
- data/app/models/plugins/ecommerce/order_detail.rb +0 -9
- data/app/models/plugins/ecommerce/payment_method.rb +0 -8
- data/app/models/plugins/ecommerce/product_item.rb +3 -10
- data/app/models/plugins/ecommerce/product_variation.rb +9 -0
- data/app/models/plugins/ecommerce/shipping_method.rb +0 -8
- data/app/models/plugins/ecommerce/tax_rate.rb +0 -8
- data/app/services/plugins/ecommerce/cart_service.rb +149 -0
- data/app/services/plugins/ecommerce/order_service.rb +26 -0
- data/app/services/plugins/ecommerce/product_item_service.rb +29 -0
- data/app/services/plugins/ecommerce/product_service.rb +17 -0
- data/app/services/plugins/ecommerce/site_service.rb +21 -0
- data/app/services/plugins/ecommerce/user_cart_service.rb +12 -0
- data/app/services/plugins/ecommerce/user_product_service.rb +29 -0
- data/app/services/plugins/ecommerce/util_service.rb +5 -0
- data/app/views/plugins/ecommerce/admin/orders/form.html.erb +28 -16
- data/app/views/plugins/ecommerce/admin/orders/index.html.erb +7 -1
- data/app/views/plugins/ecommerce/admin/payment_methods/form.html.erb +11 -1
- data/app/views/plugins/ecommerce/admin/product_attributes.html.erb +95 -0
- data/app/views/plugins/ecommerce/admin/products/_variations.html.erb +72 -0
- data/app/views/plugins/ecommerce/front/checkout/cart_index.html.erb +5 -5
- data/app/views/plugins/ecommerce/front/orders/show.html.erb +96 -89
- data/app/views/plugins/ecommerce/partials/_cart_widget.html.erb +3 -3
- data/app/views/plugins/ecommerce/partials/checkout/_details.html.erb +1 -1
- data/app/views/plugins/ecommerce/partials/checkout/_payments.html.erb +6 -1
- data/app/views/plugins/ecommerce/partials/checkout/_products_detail.html.erb +1 -1
- data/app/views/plugins/ecommerce/partials/checkout/_user_info.html.erb +26 -22
- data/app/views/post_types/commerce/single.html.erb +28 -12
- data/config/camaleon_plugin.json +4 -12
- data/config/custom_models.rb +10 -0
- data/config/locales/en.yml +3 -0
- data/config/locales/es.yml +112 -54
- data/config/routes.rb +2 -0
- data/db/migrate/20160527184747_add_new_cart_structure.rb +7 -4
- data/db/migrate/20160620200501_add_product_attributes_structure.rb +21 -0
- data/db/migrate/20160825174848_set_cama_post_decorator_class.rb +13 -0
- data/db/migrate/20160825232739_migrate_order_data.rb +87 -0
- data/lib/ecommerce/version.rb +1 -1
- metadata +22 -7
- data/app/assets/javascripts/plugins/ecommerce/admin.js +0 -0
- data/app/assets/javascripts/plugins/ecommerce/fix_form.js +0 -7
- data/config/currency_en.json +0 -154
- data/config/currency_es.json +0 -154
@@ -0,0 +1,26 @@
|
|
1
|
+
class Plugins::Ecommerce::OrderService
|
2
|
+
def initialize(site, order)
|
3
|
+
@site = site
|
4
|
+
@order = order
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :site, :order
|
8
|
+
|
9
|
+
def product_owners
|
10
|
+
owners = []
|
11
|
+
order.products.each do |product|
|
12
|
+
owners << product.owner if product.owner.present?
|
13
|
+
end
|
14
|
+
owners.uniq
|
15
|
+
end
|
16
|
+
|
17
|
+
def product_files
|
18
|
+
files = []
|
19
|
+
order.products.each do |product|
|
20
|
+
files += product.get_fields('ecommerce_files').map do |f|
|
21
|
+
CamaleonCmsLocalUploader::private_file_path(f, site)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
files.uniq
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Plugins::Ecommerce::ProductItemService
|
2
|
+
def initialize(site, product_item)
|
3
|
+
@site = site
|
4
|
+
@product_item = product_item
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :site, :product_item
|
8
|
+
|
9
|
+
def user
|
10
|
+
@user ||= product_item.cart.user
|
11
|
+
end
|
12
|
+
|
13
|
+
def product
|
14
|
+
@product ||= product_item.product
|
15
|
+
end
|
16
|
+
|
17
|
+
def decrement_qty!
|
18
|
+
available_qty = Plugins::Ecommerce::UserProductService.new(
|
19
|
+
site, user, product, product_item.variation_id).available_qty
|
20
|
+
val = (available_qty - product_item.qty).to_i
|
21
|
+
if val >= 0
|
22
|
+
if product_item.variation_id.present?
|
23
|
+
product_item.product_variation.update_column(:qty, val)
|
24
|
+
else
|
25
|
+
product.update_field_value('ecommerce_qty', val)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Plugins::Ecommerce::ProductService
|
2
|
+
def initialize(site, product, variation_id = nil)
|
3
|
+
@site = site
|
4
|
+
@product = product
|
5
|
+
@variation_id = variation_id
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :site, :product, :variation_id
|
9
|
+
|
10
|
+
def available_qty
|
11
|
+
if variation_id.present?
|
12
|
+
product.decorate.get_variation(variation_id).qty || 0
|
13
|
+
else
|
14
|
+
product.get_field_value('ecommerce_qty').to_f || 0
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Plugins::Ecommerce::SiteService
|
2
|
+
def initialize(site)
|
3
|
+
@site = site
|
4
|
+
end
|
5
|
+
|
6
|
+
attr_reader :site
|
7
|
+
|
8
|
+
def currency
|
9
|
+
site.get_meta("_setting_ecommerce", {})[:current_unit] || 'USD'
|
10
|
+
end
|
11
|
+
|
12
|
+
def payment_method(type)
|
13
|
+
payment_method = site.payment_methods.actives.detect do |payment_method|
|
14
|
+
payment_method.get_option('type') == type
|
15
|
+
end
|
16
|
+
if payment_method.nil?
|
17
|
+
raise ArgumentError, "Payment method #{type} is not found"
|
18
|
+
end
|
19
|
+
payment_method
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Plugins::Ecommerce::UserCartService
|
2
|
+
def initialize(site, user)
|
3
|
+
@site = site
|
4
|
+
@user = user
|
5
|
+
end
|
6
|
+
|
7
|
+
attr_reader :site, :user
|
8
|
+
|
9
|
+
def get_cart
|
10
|
+
site.carts.set_user(user).active_cart.first_or_create(name: "Cart by #{user.id}").decorate
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Plugins::Ecommerce::UserProductService
|
2
|
+
def initialize(site, user, product, variation_id = nil)
|
3
|
+
@site = site
|
4
|
+
@user = user
|
5
|
+
@product = product
|
6
|
+
@variation_id = variation_id
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :site, :user, :product, :variation_id
|
10
|
+
|
11
|
+
def available_qty
|
12
|
+
available_qty = Plugins::Ecommerce::ProductService.new(
|
13
|
+
site, product, variation_id).available_qty
|
14
|
+
available_qty -= qty_in_carts
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def qty_in_carts
|
20
|
+
carts = site.carts.where.not(user_id: user.id).active_cart.joins(:product_items)
|
21
|
+
if variation_id.present?
|
22
|
+
carts.where("#{Plugins::Ecommerce::ProductItemDecorator.table_name}" =>
|
23
|
+
{variation_id: variation_id}).sum("#{Plugins::Ecommerce::ProductItem.table_name}.qty")
|
24
|
+
else
|
25
|
+
carts.where("#{Plugins::Ecommerce::ProductItemDecorator.table_name}" =>
|
26
|
+
{product_id: product.id}).sum("#{Plugins::Ecommerce::ProductItem.table_name}.qty")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -1,20 +1,32 @@
|
|
1
1
|
<div class="panel panel-default">
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
2
|
+
<div class="panel-heading">
|
3
|
+
<h4><span class="fa fa-cog"></span> <%= t('plugin.ecommerce.edit_order') %>: <%= @order.slug %></h4>
|
4
|
+
</div>
|
5
|
+
<%= form_for @order, url: {action: @order.new_record? ? :create : :update}, html: {class: 'form-order', id: 'form-order'} do |f| %>
|
6
|
+
<div class="panel-body">
|
7
|
+
<%= render plugin_view('partials/checkout/user_info'), cart: @order, as_partial: true %>
|
8
|
+
<hr>
|
9
|
+
<div class="form-group">
|
10
|
+
<%= f.label nil, t('plugin.ecommerce.show_order.consignment_number', default: 'Consignment Number') %>
|
11
|
+
<%= text_field_tag 'metas[consignment_number]', @order.get_meta('consignment_number'), class: 'form-control' %>
|
12
|
+
</div>
|
13
|
+
<div class="form-group">
|
14
|
+
<%= f.label nil, t('plugins.ecommerce.front.orders.show.date_shipped', default: 'Date Shipped') %>
|
15
|
+
<div class="input-group date date-input-box">
|
16
|
+
<%= f.text_field :shipped_at, class: 'form-control' %>
|
17
|
+
<span class="add-on input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>
|
18
|
+
</div>
|
19
|
+
</div>
|
12
20
|
</div>
|
13
|
-
</div>
|
14
21
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
<div class="panel-footer">
|
23
|
+
<button class="btn btn-default" onclick="history.back()"><%= t('camaleon_cms.admin.button.back') %></button>
|
24
|
+
<button class="btn btn-primary pull-right"><%= t('camaleon_cms.admin.button.update') %></button>
|
25
|
+
</div>
|
26
|
+
<script>
|
27
|
+
jQuery(function () {
|
28
|
+
$('#form-order').find('#plugins_ecommerce_order_shipped_at').parent().datetimepicker({ format: 'YYYY-MM-DD HH:mm' });;
|
29
|
+
})
|
30
|
+
</script>
|
31
|
+
<% end %>
|
20
32
|
</div>
|
@@ -88,7 +88,13 @@
|
|
88
88
|
%>
|
89
89
|
<tr>
|
90
90
|
<td><%= order.slug %></td>
|
91
|
-
<td
|
91
|
+
<td>
|
92
|
+
<% if order.user %>
|
93
|
+
<%= order.user.fullname %>
|
94
|
+
<% else %>
|
95
|
+
<small>(No user)</small>
|
96
|
+
<% end %>
|
97
|
+
</td>
|
92
98
|
<td><%= raw order.the_status %></td>
|
93
99
|
<td><%= order.paid? ? 'Yes' : 'No' %></td>
|
94
100
|
<td>
|
@@ -30,9 +30,11 @@
|
|
30
30
|
<ul class="nav nav-tabs nav-justified">
|
31
31
|
<li class="<%= 'active' if options[:type] == 'bank_transfer' %>"><a href="#tab8" data-toggle="tab"><%= t('plugin.ecommerce.by_bank_transfer') %></a></li>
|
32
32
|
<li class="<%= 'active' if options[:type] == 'paypal' %>"><a href="#tab9" data-toggle="tab"><%= t('plugin.ecommerce.by_paypal') %></a></li>
|
33
|
-
<!--<li class="<%= 'active' if options[:type] == 'credit_card' %>"><a href="#tab7" data-toggle="tab"><%= t('plugin.ecommerce.by_credit_card') %></a></li>-->
|
34
33
|
<li class="<%= 'active' if options[:type] == 'authorize_net' %>"><a href="#tab10" data-toggle="tab"><%= t('plugin.ecommerce.by_authorize_net') %></a></li>
|
35
34
|
<li class="<%= 'active' if options[:type] == 'stripe' %>"><a href="#tab11" data-toggle="tab"><%= t('plugin.ecommerce.by_stripe', default: 'Stripe') %></a></li>
|
35
|
+
<% ecommerce_custom_payment_methods.each do |k, obj| %>
|
36
|
+
<li class="<%= 'active' if options[:type] == k %>"><a href="#tab_<%= k %>" data-toggle="tab"><%= obj[:title] %></a></li>
|
37
|
+
<% end %>
|
36
38
|
</ul>
|
37
39
|
<div class="panel-body tab-content">
|
38
40
|
|
@@ -115,6 +117,14 @@
|
|
115
117
|
<%= text_field_tag('options[stripe_key]', options[:stripe_key], class: 'form-control required') %>
|
116
118
|
</div>
|
117
119
|
</div>
|
120
|
+
|
121
|
+
<% ecommerce_custom_payment_methods.each do |k, obj| %>
|
122
|
+
<div class="tab-pane <%= 'active' if options[:type] == k %>" id="tab_<%= k %>">
|
123
|
+
<%= hidden_field_tag('options[type]', k) %>
|
124
|
+
<%= render obj[:settings_view_path], options: options %>
|
125
|
+
</div>
|
126
|
+
<% end %>
|
127
|
+
|
118
128
|
</div>
|
119
129
|
</div>
|
120
130
|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
<%= form_tag url_for(action: :save_product_attributes), class: 'panel panel-default', id: 'ecommerce_product_attributes', 'data-confirm-msg' => t('.confirm_delete', default: 'Are you sure to delete?') do %>
|
2
|
+
<div class="panel-heading ui-draggable-handle">
|
3
|
+
<h3 class="panel-title"><%= t('.title', default: 'Product Attributes') %></h3>
|
4
|
+
</div>
|
5
|
+
<div class="panel-body">
|
6
|
+
<% (current_site.product_attributes.to_a + [Plugins::Ecommerce::Attribute.new]).each_with_index do |attr, index| %>
|
7
|
+
<div data-id="<%= attr.id %>" class="panel panel-info attribute_group attribute_<%= attr.id %> <%= 'hidden' unless attr.id.present? %>">
|
8
|
+
<div class="panel-heading">
|
9
|
+
<h3 class="panel-title"> </h3>
|
10
|
+
<ul class="panel-controls">
|
11
|
+
<li><a href="#" class="del_group"><i class="fa fa-times"></i></a></li>
|
12
|
+
<li><a class="hidden group_sorter"><i class="fa fa-arrows" style="cursor: move"></i></a></li>
|
13
|
+
<li><a class="panel-collapse" href="#"><span class="fa fa-angle-down"></span></a></li>
|
14
|
+
</ul>
|
15
|
+
</div>
|
16
|
+
<div class="panel-body">
|
17
|
+
<div class="form-group">
|
18
|
+
<label><%= t('.group_label', default: 'Group Label') %></label>
|
19
|
+
<%= text_field_tag "attribute_names[#{attr.id}][label]", attr.label, class: 'form-control translatable required' %>
|
20
|
+
</div>
|
21
|
+
<label><%= t('.values', default: 'Values') %></label>
|
22
|
+
<hr>
|
23
|
+
<div class="item-custom-field">
|
24
|
+
<div class="actions"></div>
|
25
|
+
<div class="row group-input-fields-content">
|
26
|
+
<div class="col-md-4">
|
27
|
+
<label><%= t('.code', default: 'Code') %></label><em class="text-danger">*</em><br>
|
28
|
+
</div>
|
29
|
+
<div class="col-md-8">
|
30
|
+
<label><%= t('.value', default: 'Value') %></label><em class="text-danger">*</em><br>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
<ul class="values_sortable">
|
35
|
+
<% (attr.values.to_a + (attr.id.present? ? [] : [Plugins::Ecommerce::Attribute.new])).each do |value| %>
|
36
|
+
<li class="item-custom-field product_attribute_value_<%= value.id %>">
|
37
|
+
<%= hidden_field_tag "attribute[#{attr.id}][][position]", value.position, class: 'value_position' %>
|
38
|
+
<%= hidden_field_tag "attribute[#{attr.id}][][id]", value.id %>
|
39
|
+
<div class="actions">
|
40
|
+
<i style="cursor: move" class="fa fa-arrows values_sorter"></i>
|
41
|
+
<a href="#" class="del"><i class="fa fa-times"></i></a>
|
42
|
+
</div>
|
43
|
+
<div class="group-input-fields-content row">
|
44
|
+
<div class="col-md-4">
|
45
|
+
<%= text_field_tag "attribute[#{attr.id}][][key]", value.key, class: 'form-control slug required', "data-parent" => "category_name", style: "#{'margin-top: 47px;' if current_site.get_languages.count > 1 }" %>
|
46
|
+
</div>
|
47
|
+
<div class="col-md-8">
|
48
|
+
<%= text_field_tag "attribute[#{attr.id}][][value]", value.label, class: 'form-control required translatable' %>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
</li>
|
52
|
+
<% end %>
|
53
|
+
</ul>
|
54
|
+
<div> <a href="#" class="btn btn-warning btn-xs add_new_value"> <i class="fa fa-plus"></i> <%= t('.add_new_value', default: 'Add new value') %></a></div>
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
</div>
|
60
|
+
<div class="panel-footer text-right">
|
61
|
+
<a class="btn btn-default pull-left" href="<%= url_for action: :index %>" role="back"><%= t('camaleon_cms.admin.button.back', default: 'Back')%></a>
|
62
|
+
<a class="btn btn-default add_new_group"><%= t('.add_attr_group', default: 'Add new group')%></a>
|
63
|
+
<button class="btn btn-primary" type="submit"><%= t('camaleon_cms.admin.button.submit', default: 'Save')%></button>
|
64
|
+
</div>
|
65
|
+
<% end %>
|
66
|
+
<script>
|
67
|
+
jQuery(function(){
|
68
|
+
var groups_counter = 1;
|
69
|
+
var panel = $('#ecommerce_product_attributes');
|
70
|
+
var val_cache = panel.find('.product_attribute_value_').remove().clone();
|
71
|
+
var p_cache = panel.find('.panel.attribute_').remove().clone().removeClass('hidden');
|
72
|
+
var after_reorder = function(){ $(this).children().each(function(index){ $(this).find('input.value_position').val(index); }) }
|
73
|
+
panel.find('.add_new_group').click(function(){
|
74
|
+
var g = p_cache.clone().attr('data-id', 'new_'+groups_counter);
|
75
|
+
panel.children('.panel-body').append(g);
|
76
|
+
g.find('input').each(function(){ $(this).attr('name', $(this).attr('name').replace('[]', '['+g.attr('data-id')+']')) });
|
77
|
+
g.find('.translatable').Translatable();
|
78
|
+
g.find('.add_new_value').click();
|
79
|
+
g.find('.values_sortable').sortable({handle: '.values_sorter', update: after_reorder})
|
80
|
+
return false;
|
81
|
+
});
|
82
|
+
|
83
|
+
panel.on('click', '.add_new_value', function(){
|
84
|
+
var g = $(this).closest('.attribute_group');
|
85
|
+
var clone = val_cache.clone();
|
86
|
+
clone.find('input').each(function(){ $(this).attr('name', $(this).attr('name').replace('[]', '['+g.attr('data-id')+']')) });
|
87
|
+
clone.find('.translatable').Translatable();
|
88
|
+
g.find('.panel-body > ul').append(clone);
|
89
|
+
return false;
|
90
|
+
});
|
91
|
+
panel.find('.values_sortable').sortable({handle: '.values_sorter', update: after_reorder})
|
92
|
+
panel.on('click', '.item-custom-field a.del', function(){ if(!confirm(panel.attr('data-confirm-msg'))) return false; $(this).closest('li').fadeOut('slow', function(){ $(this).remove(); }); return false; });
|
93
|
+
panel.on('click', 'a.del_group', function(){ if(!confirm(panel.attr('data-confirm-msg'))) return false; $(this).closest('.attribute_group').fadeOut('slow', function(){ $(this).remove(); }); return false; });
|
94
|
+
});
|
95
|
+
</script>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
<% field = post_type.get_field_object('ecommerce_photos') %>
|
2
|
+
<div class="panel panel-default hidden" id="product_variations" data-confirm-msg="<%= t('.confirm_del', default: 'Are you sure to delete this variation?') %>">
|
3
|
+
<div class="panel-heading ">
|
4
|
+
<h3 class="panel-title"><%= t('.title', default: 'Product Variations') %></h3>
|
5
|
+
</div>
|
6
|
+
<div class="panel-body variations_sortable">
|
7
|
+
<% (product.product_variations.to_a + [Plugins::Ecommerce::ProductVariation.new]).each do |variation| %>
|
8
|
+
<div class="panel panel-info product_variation <%= 'blank_product_variation hidden' unless variation.id.present? %>" data-id="<%= variation.id %>">
|
9
|
+
<div class="panel-heading">
|
10
|
+
<h3 class="panel-title"> </h3>
|
11
|
+
<ul class="panel-controls">
|
12
|
+
<li><a class="var_del" href="#"><i class="fa fa-times text-danger"></i></a></li>
|
13
|
+
<li><a class="variation_sorter"><i class="fa fa-arrows" style="cursor: move"></i></a></li>
|
14
|
+
<li><a class="panel-collapse" href="#"><span class="fa fa-angle-down"></span></a></li>
|
15
|
+
</ul>
|
16
|
+
</div>
|
17
|
+
<div class="panel-body">
|
18
|
+
<%= hidden_field_tag "product_variation[#{variation.id}][position]", variation.position, class: 'product_variation_position' %>
|
19
|
+
<div class="variation_attributes form-group">
|
20
|
+
<label><%= t('.attributes', default: 'Attributes') %></label>
|
21
|
+
<ul class="item-custom-field sortable_values">
|
22
|
+
<% (variation.id.present? ? variation.attribute_values : [variation.attribute_values.rewhere(id: nil).new]).each do |val| %>
|
23
|
+
<li>
|
24
|
+
<div class="actions">
|
25
|
+
<a class="val_sorter"><i class="fa fa-arrows" style="cursor: move"></i></a>
|
26
|
+
<a href="#" class="val_del "><i class="fa fa-times text-danger"></i></a>
|
27
|
+
</div>
|
28
|
+
<div class="row group-input-fields-content">
|
29
|
+
<div class="col-md-4">
|
30
|
+
<%= select_tag "product_variation[#{variation.id}][attributes][][id]", options_from_collection_for_select(current_site.product_attributes, :id, :label, val.parent_id), class: 'form-control required product_attribute_select' %>
|
31
|
+
</div>
|
32
|
+
<div class="col-md-8">
|
33
|
+
<%= select_tag "product_variation[#{variation.id}][attributes][][value]", val.id.present? ? options_from_collection_for_select(val.product_attribute.values, :id, :label, val.id) : [], class: 'form-control required product_attribute_vals_select' %>
|
34
|
+
</div>
|
35
|
+
</div>
|
36
|
+
</li>
|
37
|
+
<% end %>
|
38
|
+
</ul>
|
39
|
+
<div> <a href="#" class="btn btn-warning btn-xs add_new_value"> <i class="fa fa-plus"></i> <%= t('.add_new_value', default: 'Add new value') %></a></div>
|
40
|
+
</div>
|
41
|
+
<div class="form-group">
|
42
|
+
<label><%= t('.photo', default: 'Photo') %></label><em class="text-danger">*</em><br>
|
43
|
+
<div class=" input-group">
|
44
|
+
<%= url_field_tag "product_variation[#{variation.id}][photo]", variation.photo, data:{dimension: field.options[:dimension], versions: field.options[:versions], thumb_size: field.options[:thumb_size]}, class: 'data-error-place-parent form-control required' %>
|
45
|
+
<a href="#" class="input-group-addon product_variation_photo_link"><i class="fa fa-upload"></i> <%= t('camaleon_cms.admin.button.upload_image', default: 'Upload Photo')%> <%= "(#{field.get_option('dimension')})" if field.get_option('dimension').present? %></a>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
<div class="form-group">
|
49
|
+
<label><%= t('.sku', default: 'SKU') %></label><em class="text-danger">*</em><br>
|
50
|
+
<%= text_field_tag "product_variation[#{variation.id}][sku]", variation.sku, class: 'form-control required' %>
|
51
|
+
</div>
|
52
|
+
<div class="form-group">
|
53
|
+
<label><%= t('.price', default: 'Price') %></label><em class="text-danger">*</em><br>
|
54
|
+
<%= number_field_tag "product_variation[#{variation.id}][price]", variation.amount, class: 'form-control required number' %>
|
55
|
+
</div>
|
56
|
+
<div class="form-group">
|
57
|
+
<label><%= t('.weight', default: 'Weight') %></label><em class="text-danger">*</em><br>
|
58
|
+
<%= number_field_tag "product_variation[#{variation.id}][weight]", variation.weight, class: 'form-control required number' %>
|
59
|
+
</div>
|
60
|
+
<div class="form-group">
|
61
|
+
<label><%= t('.qty', default: 'Quantity') %></label>
|
62
|
+
<%= number_field_tag "product_variation[#{variation.id}][qty]", variation.qty, class: 'form-control number' %>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
</div>
|
66
|
+
<% end %>
|
67
|
+
</div>
|
68
|
+
<div class="panel-footer text-right">
|
69
|
+
<a class="btn btn-warning add_new_variation btn-xs" href="#"><i class="fa fa-plus"></i> <%= t('.add_new_variation', default: 'Add new variation') %></a>
|
70
|
+
</div>
|
71
|
+
</div>
|
72
|
+
<script>var PRODUCT_ATTRIBUTES = <%= raw current_site.product_attributes.to_json(include: :values) %></script>
|
@@ -16,16 +16,16 @@
|
|
16
16
|
<tbody>
|
17
17
|
<% @products.each do |item| product = item.product.decorate %>
|
18
18
|
<tr>
|
19
|
-
<td><a href="<%= product.the_url %>"><%= product.
|
19
|
+
<td><a href="<%= product.the_url %>"><%= product.the_variation_title(item.variation_id) %></a></td>
|
20
20
|
<td><%= item.the_price %></td>
|
21
|
-
<td><%=
|
21
|
+
<td><%= item.the_tax %></td>
|
22
22
|
<td>
|
23
|
-
<input name="
|
24
|
-
<input class="text-qty" type="number" name="
|
23
|
+
<input name="product_items[][item_id]" type="hidden" value="<%= item.id %>"/>
|
24
|
+
<input class="text-qty" type="number" name="product_items[][qty]" value="<%= item.qty %>">
|
25
25
|
</td>
|
26
26
|
<td><%= item.the_sub_total %></td>
|
27
27
|
<td>
|
28
|
-
<a rel="nofollow" data-method="delete" href="<%= plugins_ecommerce_checkout_cart_remove_path(
|
28
|
+
<a rel="nofollow" data-method="delete" href="<%= plugins_ecommerce_checkout_cart_remove_path(product_item_id: item.id) %>"><%= t('.delete', default: 'Remove') %></a>
|
29
29
|
</td>
|
30
30
|
</tr>
|
31
31
|
<% end %>
|
@@ -1,17 +1,20 @@
|
|
1
1
|
<% order ||= @order %>
|
2
2
|
<div class="order_details">
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
<
|
8
|
-
|
9
|
-
<
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
3
|
+
<% unless defined?(as_partial) %>
|
4
|
+
<h1><%= t('.title', default: 'Order Details') %>: <%= order.slug %></h1>
|
5
|
+
<% end %>
|
6
|
+
<div>
|
7
|
+
<h4><%= t('.customer_info', default: 'Customer Info') %></h4>
|
8
|
+
<ul class="ec-list-orders-address">
|
9
|
+
<li><strong><%= t('.name', default: 'Name') %>:</strong> <span> <%= order.user.fullname %></span></li>
|
10
|
+
<li><strong><%= t('.email', default: 'Email') %>:</strong> <span> <%= order.user.email %></span></li>
|
11
|
+
<li><strong><%= t('.phone', default: 'Phone') %>:</strong>
|
12
|
+
<span> <%= order.user.get_option('phone') %></span></li>
|
13
|
+
</ul>
|
14
|
+
</div>
|
14
15
|
|
16
|
+
<div class="row">
|
17
|
+
<div class="col-md-6">
|
15
18
|
<h4><%= t('.billing_address', default: 'Billing Address') %></h4>
|
16
19
|
<% detail = order.get_meta("billing_address", {}) %>
|
17
20
|
<ul class="ec-list-orders-address">
|
@@ -21,11 +24,13 @@
|
|
21
24
|
<li><strong><%= t('.state', default: 'State') %>:</strong> <%= detail[:state] %></li>
|
22
25
|
<li><strong><%= t('.zip_code', default: 'Zip code') %>:</strong> <%= detail[:zip] %></li>
|
23
26
|
<li><strong><%= t('.country', default: 'Country') %>:</strong> <%= detail[:country] %></li>
|
27
|
+
<li><strong><%= t('.phone_number', default: 'Phone Number') %>:</strong> <%= detail[:phone_number] %>
|
28
|
+
</li>
|
24
29
|
</ul>
|
25
30
|
</div>
|
26
31
|
<div class="col-md-6">
|
27
|
-
|
28
|
-
|
32
|
+
<h4><%= t('.shipping_address', default: 'Shipping Address') %></h4>
|
33
|
+
<% detail = order.get_meta("shipping_address", {}) %>
|
29
34
|
<ul class="ec-list-orders-address">
|
30
35
|
<li><strong><%= t('.address', default: 'Address1') %>:</strong> <%= detail[:address1] %></li>
|
31
36
|
<li><strong><%= t('.address', default: 'Address') %>2:</strong> <%= detail[:address2] %></li>
|
@@ -33,98 +38,100 @@
|
|
33
38
|
<li><strong><%= t('.state', default: 'State') %>:</strong> <%= detail[:state] %></li>
|
34
39
|
<li><strong><%= t('.zip_code', default: 'Zip code') %>:</strong> <%= detail[:zip] %></li>
|
35
40
|
<li><strong><%= t('.country', default: 'Country') %>:</strong> <%= detail[:country] %></li>
|
41
|
+
<li><strong><%= t('.phone_number', default: 'Phone Number') %>:</strong> <%= detail[:phone_number] %>
|
42
|
+
</li>
|
36
43
|
</ul>
|
37
44
|
</div>
|
38
|
-
|
45
|
+
</div>
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
<div class="row">
|
48
|
+
<div class="col-md-12">
|
49
|
+
<h4><%= t('.title_products', default: 'Products and Payments') %></h4>
|
50
|
+
<div id="totals_section">
|
51
|
+
<table class="table table-bordered">
|
52
|
+
<tbody>
|
53
|
+
<tr>
|
54
|
+
<th id="quantity_col"><%= t('.qty', default: 'Quantity') %></th>
|
55
|
+
<th id="item_col"><%= t('.item', default: 'Item') %></th>
|
56
|
+
<th id="price_col"><%= t('.price', default: 'Price') %></th>
|
50
57
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
<th id="tax_col"><%= t('.tax', default: 'Tax') %></th>
|
59
|
+
<th id="subtotal_col"><%= t('.subtotal', default: 'Sub Total') %></th>
|
60
|
+
</tr>
|
61
|
+
<% order.product_items.each do |item| %>
|
62
|
+
<tr>
|
63
|
+
<td><%= item.qty %></td>
|
64
|
+
<td><%= link_to(item.cache_the_title, item.product.try(:decorate).try(:the_url)) %></td>
|
65
|
+
<td><%= item.cache_the_price %></td>
|
66
|
+
<td><%= item.cache_the_tax %></td>
|
67
|
+
<td><%= item.cache_the_sub_total %></td>
|
68
|
+
</tr>
|
69
|
+
<% end %>
|
55
70
|
<tr>
|
56
|
-
<td
|
57
|
-
<td><%=
|
58
|
-
<td><%=
|
59
|
-
<td><%= item.cache_the_tax %></td>
|
60
|
-
<td><%= item.cache_the_sub_total %></td>
|
71
|
+
<td colspan="2"></td>
|
72
|
+
<td colspan="2" class="text-right"><%= t('.total_excl', default: 'Total (excluding Tax)') %> </td>
|
73
|
+
<td><%= order.cache_the_sub_total %></td>
|
61
74
|
</tr>
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
<tr>
|
76
|
+
<td colspan="2"></td>
|
77
|
+
<td colspan="2" class="text-right"><%= t('.tax', default: 'Tax') %></td>
|
78
|
+
<td id="tax_total"><%= order.cache_the_tax %></td>
|
79
|
+
</tr>
|
80
|
+
<tr>
|
81
|
+
<td colspan="2"></td>
|
82
|
+
<td colspan="2" class="text-right"><%= t('.discount', default: 'Discount') %></td>
|
83
|
+
<td><%= order.cache_the_discounts %></td>
|
84
|
+
</tr>
|
85
|
+
<tr>
|
86
|
+
<td colspan="2"></td>
|
87
|
+
<td colspan="2" class="text-right"><%= t('.total_shipping', default: 'Total shipping') %></td>
|
88
|
+
<td><%= order.cache_the_shipping %></td>
|
89
|
+
</tr>
|
90
|
+
<tr>
|
91
|
+
<td colspan="2"></td>
|
92
|
+
<td colspan="2" class="text-right"><%= t('.total_price', default: 'Total Price') %></td>
|
93
|
+
<td><%= order.cache_the_total %></td>
|
94
|
+
</tr>
|
95
|
+
</tbody>
|
96
|
+
</table>
|
97
|
+
</div>
|
98
|
+
|
99
|
+
<table class="table table-bordered">
|
100
|
+
<tbody>
|
68
101
|
<tr>
|
69
|
-
<
|
70
|
-
<
|
71
|
-
<td id="tax_total"><%= order.cache_the_tax %></td>
|
102
|
+
<th><%= t('.payment_type', default: 'Type Payment') %></th>
|
103
|
+
<th></th>
|
72
104
|
</tr>
|
73
105
|
<tr>
|
74
|
-
<td
|
75
|
-
<td
|
76
|
-
<td><%= order.cache_the_discounts %></td>
|
106
|
+
<td><%= order.payment_method.name rescue 'Not Payment' %></td>
|
107
|
+
<td><%= raw order.the_status %></td>
|
77
108
|
</tr>
|
109
|
+
<% if defined?(as_partial) %>
|
110
|
+
<tr>
|
111
|
+
<td>
|
112
|
+
<%= raw order.get_meta('payment_data', {}).map { |k, v| "<b>#{k.to_s.titleize}</b>: #{v}" }.join('<br>') %>
|
113
|
+
</td>
|
114
|
+
</tr>
|
115
|
+
<% end %>
|
116
|
+
</tbody>
|
117
|
+
</table>
|
118
|
+
|
119
|
+
<table class="table table-bordered">
|
120
|
+
<tbody>
|
78
121
|
<tr>
|
79
|
-
<
|
80
|
-
<
|
81
|
-
<
|
122
|
+
<th><%= t('.shipping_method', default: 'Shipping Method') %></th>
|
123
|
+
<th><%= t('.date_shipped', default: 'Shipped Date') %></th>
|
124
|
+
<th><%= t('.track_url', default: 'URL Tracking') %></th>
|
82
125
|
</tr>
|
83
126
|
<tr>
|
84
|
-
<td
|
85
|
-
<td
|
86
|
-
<td><%= order.
|
127
|
+
<td><%= order.shipping_method.name rescue t('.no_shipping', default: 'Not Shipped Assigned') %></td>
|
128
|
+
<td><%= order.shipped_at.presence || t('.no_shipped', default: 'Not Shipped') %></td>
|
129
|
+
<td><%= order.the_url_tracking %></td>
|
87
130
|
</tr>
|
88
131
|
</tbody>
|
89
132
|
</table>
|
133
|
+
<div class="text-center">
|
134
|
+
</div>
|
90
135
|
</div>
|
91
|
-
|
92
|
-
<table class="table table-bordered">
|
93
|
-
<tbody>
|
94
|
-
<tr>
|
95
|
-
<th><%= t('.payment_type', default: 'Type Payment') %></th>
|
96
|
-
<th></th>
|
97
|
-
</tr>
|
98
|
-
<tr>
|
99
|
-
<td><%= order.payment_method.name rescue 'Not Payment' %></td>
|
100
|
-
<td><%= raw order.the_status %></td>
|
101
|
-
</tr>
|
102
|
-
<% if defined?(as_partial) %>
|
103
|
-
<tr>
|
104
|
-
<td>
|
105
|
-
<%= raw order.get_meta('payment_data', {}).map{|k, v| "<b>#{k.to_s.titleize}</b>: #{v}" }.join('<br>') %>
|
106
|
-
</td>
|
107
|
-
</tr>
|
108
|
-
<% end %>
|
109
|
-
</tbody>
|
110
|
-
</table>
|
111
|
-
|
112
|
-
<table class="table table-bordered">
|
113
|
-
<tbody>
|
114
|
-
<tr>
|
115
|
-
<th><%= t('.shipping_method', default: 'Shipping Method') %></th>
|
116
|
-
<th><%= t('.date_shipped', default: 'Shipped Date') %></th>
|
117
|
-
<th><%= t('.track_url', default: 'URL Tracking') %></th>
|
118
|
-
</tr>
|
119
|
-
<tr>
|
120
|
-
<td><%= order.shipping_method.name rescue t('.no_shipping', default: 'Not Shipped Assigned') %></td>
|
121
|
-
<td><%= order.shipped_at.presence || t('.no_shipped', default: 'Not Shipped') %></td>
|
122
|
-
<td><%= order.the_url_tracking %></td>
|
123
|
-
</tr>
|
124
|
-
</tbody>
|
125
|
-
</table>
|
126
|
-
<div class="text-center">
|
127
|
-
</div>
|
128
136
|
</div>
|
129
|
-
</div>
|
130
137
|
</div>
|