camaleon_ecommerce 1.1 → 1.2
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.
- 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>
|