spree_core 1.0.4 → 1.0.6
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.
- data/app/assets/javascripts/admin/admin.js.erb +18 -9
- data/app/assets/javascripts/admin/checkouts/edit.js +2 -2
- data/app/assets/stylesheets/admin/admin.css.erb +4 -2
- data/app/controllers/spree/admin/orders/customer_details_controller.rb +2 -2
- data/app/controllers/spree/admin/payments_controller.rb +1 -1
- data/app/models/spree/address.rb +6 -1
- data/app/models/spree/adjustment.rb +4 -2
- data/app/models/spree/calculator/default_tax.rb +2 -0
- data/app/models/spree/calculator/flat_percent_item_total.rb +4 -0
- data/app/models/spree/calculator/flat_rate.rb +4 -0
- data/app/models/spree/calculator/flexi_rate.rb +4 -0
- data/app/models/spree/calculator/per_item.rb +4 -0
- data/app/models/spree/calculator/price_sack.rb +6 -0
- data/app/models/spree/creditcard.rb +9 -6
- data/app/models/spree/gateway.rb +2 -0
- data/app/models/spree/image.rb +3 -0
- data/app/models/spree/mail_method.rb +7 -0
- data/app/models/spree/option_type.rb +2 -0
- data/app/models/spree/option_value.rb +2 -0
- data/app/models/spree/order.rb +1 -1
- data/app/models/spree/payment.rb +2 -0
- data/app/models/spree/payment_method.rb +2 -0
- data/app/models/spree/preference.rb +1 -0
- data/app/models/spree/product.rb +9 -1
- data/app/models/spree/product/scopes.rb +39 -34
- data/app/models/spree/product_property.rb +2 -0
- data/app/models/spree/property.rb +2 -0
- data/app/models/spree/prototype.rb +4 -0
- data/app/models/spree/return_authorization.rb +2 -0
- data/app/models/spree/role.rb +2 -0
- data/app/models/spree/shipment.rb +4 -0
- data/app/models/spree/shipping_category.rb +2 -0
- data/app/models/spree/shipping_method.rb +3 -0
- data/app/models/spree/state.rb +2 -0
- data/app/models/spree/tax_category.rb +2 -0
- data/app/models/spree/tax_rate.rb +2 -0
- data/app/models/spree/taxon.rb +2 -0
- data/app/models/spree/taxonomy.rb +2 -0
- data/app/models/spree/tracker.rb +2 -0
- data/app/models/spree/user.rb +1 -0
- data/app/models/spree/variant.rb +5 -0
- data/app/models/spree/zone.rb +2 -0
- data/app/models/spree/zone_member.rb +2 -0
- data/app/views/spree/admin/mail_methods/_form.html.erb +1 -1
- data/app/views/spree/admin/payment_methods/_form.html.erb +1 -1
- data/app/views/spree/admin/shared/_head.html.erb +3 -3
- data/app/views/spree/admin/tax_rates/index.html.erb +1 -1
- data/app/views/spree/admin/trackers/_form.html.erb +1 -1
- data/config/locales/en.yml +4 -0
- data/config/routes.rb +3 -3
- data/db/migrate/20120523061241_convert_sales_tax_to_default_tax.rb +9 -0
- data/lib/spree/core/calculated_adjustments.rb +6 -5
- data/lib/spree/core/ssl_requirement.rb +2 -2
- data/lib/spree/core/testing_support/fixtures.rb +4 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/product_filters.rb +16 -7
- metadata +35 -36
@@ -1,3 +1,4 @@
|
|
1
|
+
<%# encoding: utf-8 %>
|
1
2
|
//= require_self
|
2
3
|
|
3
4
|
/**
|
@@ -59,8 +60,10 @@ format_product_autocomplete = function(item){
|
|
59
60
|
}
|
60
61
|
|
61
62
|
html += "<div><h4>" + product['name'] + "</h4>";
|
62
|
-
|
63
|
-
|
63
|
+
if (product['master']) {
|
64
|
+
html += "<span><strong><%= ::I18n.t(:sku) %>: </strong>" + product['master']['sku'] + "</span>";
|
65
|
+
}
|
66
|
+
html += "<span><strong><%= ::I18n.t(:on_hand) %>: </strong>" + product['count_on_hand'] + "</span></div>";
|
64
67
|
}else{
|
65
68
|
// variant
|
66
69
|
var variant = item.data['variant'];
|
@@ -75,12 +78,12 @@ format_product_autocomplete = function(item){
|
|
75
78
|
}
|
76
79
|
|
77
80
|
name += " - " + $.map(variant['option_values'], function(option_value){
|
78
|
-
return option_value["option_type"]["presentation"] + ": " + option_value['
|
81
|
+
return option_value["option_type"]["presentation"] + ": " + option_value['presentation'];
|
79
82
|
}).join(", ")
|
80
83
|
|
81
84
|
html += "<div><h4>" + name + "</h4>";
|
82
|
-
html += "<span><strong
|
83
|
-
html += "<span><strong
|
85
|
+
html += "<span><strong><%= ::I18n.t(:sku) %>: </strong>" + variant['sku'] + "</span>";
|
86
|
+
html += "<span><strong><%= ::I18n.t(:on_hand) %>: </strong>" + variant['count_on_hand'] + "</span></div>";
|
84
87
|
}
|
85
88
|
|
86
89
|
return html
|
@@ -97,7 +100,7 @@ prep_product_autocomplete_data = function(data){
|
|
97
100
|
|
98
101
|
var name = product['name'];
|
99
102
|
name += " - " + $.map(variant['option_values'], function(option_value){
|
100
|
-
return option_value["option_type"]["presentation"] + ": " + option_value['
|
103
|
+
return option_value["option_type"]["presentation"] + ": " + option_value['presentation'];
|
101
104
|
}).join(", ");
|
102
105
|
|
103
106
|
return {
|
@@ -120,7 +123,7 @@ $.fn.product_autocomplete = function(){
|
|
120
123
|
return this.each(function() {
|
121
124
|
$(this).autocomplete({
|
122
125
|
source: function(request, response) {
|
123
|
-
$.get("
|
126
|
+
$.get(ajax_urls.product_search_json + "?q=" + $('#add_product_name').val() + "&authenticity_token=" + encodeURIComponent($('meta[name=csrf-token]').attr("content")), function(data) {
|
124
127
|
result = prep_product_autocomplete_data(data)
|
125
128
|
response(result);
|
126
129
|
});
|
@@ -171,8 +174,9 @@ $.fn.objectPicker = function(url){
|
|
171
174
|
$.fn.productPicker = function(){
|
172
175
|
$(this).objectPicker(ajax_urls.product_search_basic_json);
|
173
176
|
}
|
177
|
+
|
174
178
|
$.fn.userPicker = function(){
|
175
|
-
$(this).objectPicker(ajax_urls.
|
179
|
+
$(this).objectPicker(ajax_urls.user_search_json);
|
176
180
|
}
|
177
181
|
|
178
182
|
// Possible defunct
|
@@ -206,7 +210,12 @@ $(".observe_field").live('change', function() {
|
|
206
210
|
|
207
211
|
handle_date_picker_fields = function(){
|
208
212
|
$('.datepicker').datepicker({
|
209
|
-
dateFormat: 'yy/mm/dd',
|
213
|
+
dateFormat: "<%= ::I18n.t(:format, :scope => 'spree.date_picker', :default => 'yy/mm/dd') %>",
|
214
|
+
dayNames: ["<%= ::I18n.t(:day_names, :scope => :date).join('","') %>"],
|
215
|
+
dayNamesMin: ["<%= ::I18n.t(:abbr_day_names, :scope => :date).join('","') %>"],
|
216
|
+
monthNames: ["<%= ::I18n.t(:month_names, :scope => :date).join('","') %>"],
|
217
|
+
prevText: '<%= ::I18n.t(:previous) %>',
|
218
|
+
nextText: '<%= ::I18n.t(:next) %>',
|
210
219
|
showOn: "button",
|
211
220
|
buttonImage: "<%= asset_path 'datepicker/cal.gif' %>",
|
212
221
|
buttonImageOnly: true
|
@@ -46,7 +46,7 @@ $(document).ready(function(){
|
|
46
46
|
minChars: 5,
|
47
47
|
delay: 1500,
|
48
48
|
source: function(request, response) {
|
49
|
-
$.get("
|
49
|
+
$.get(ajax_urls.user_search_json + "&q=" + $("#customer_search").val() + "&authenticity_token=" + encodeURIComponent($('meta[name=csrf-token]').attr("content")), function(data) {
|
50
50
|
result = prep_user_autocomplete_data(data)
|
51
51
|
response(result);
|
52
52
|
});
|
@@ -78,6 +78,7 @@ $(document).ready(function(){
|
|
78
78
|
$('#user_id').val(ui.item.data['id']);
|
79
79
|
$('#guest_checkout_true').prop("checked", false);
|
80
80
|
$('#guest_checkout_false').prop("checked", true);
|
81
|
+
$('#guest_checkout_false').prop("disabled", false);
|
81
82
|
return true;
|
82
83
|
}
|
83
84
|
}).data("autocomplete")._renderItem = function(ul, item) {
|
@@ -107,7 +108,6 @@ $(document).ready(function(){
|
|
107
108
|
$('#customer_search').val("");
|
108
109
|
$('#user_id').val("");
|
109
110
|
$('#checkout_email').val("");
|
110
|
-
$('#guest_checkout_false').prop("disabled", true);
|
111
111
|
|
112
112
|
$('#order_bill_address_attributes_firstname').val("");
|
113
113
|
$('#order_bill_address_attributes_lastname').val("");
|
@@ -313,7 +313,7 @@ body {
|
|
313
313
|
width: 24px; }
|
314
314
|
button.small {
|
315
315
|
font-size: 1em;
|
316
|
-
padding: 0
|
316
|
+
padding: 0 20px 0 0;
|
317
317
|
}
|
318
318
|
input.title,
|
319
319
|
textarea {
|
@@ -597,7 +597,9 @@ span.handle{
|
|
597
597
|
border: 1px solid #000;
|
598
598
|
}
|
599
599
|
|
600
|
-
.ac_results li
|
600
|
+
.ac_results li div { max-width: 90%; }
|
601
|
+
|
602
|
+
.ac_results li h4 { width: 100%; }
|
601
603
|
|
602
604
|
.ac_results li:last-child { border: none; }
|
603
605
|
|
@@ -10,8 +10,8 @@ module Spree
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def edit
|
13
|
-
@order.
|
14
|
-
@order.
|
13
|
+
@order.bill_address = Address.default if @order.bill_address.nil?
|
14
|
+
@order.ship_address = Address.default if @order.ship_address.nil?
|
15
15
|
end
|
16
16
|
|
17
17
|
def update
|
@@ -46,7 +46,7 @@ module Spree
|
|
46
46
|
|
47
47
|
rescue Spree::Core::GatewayError => e
|
48
48
|
flash[:error] = "#{e.message}"
|
49
|
-
respond_with(@payment) { |format| format.html { redirect_to
|
49
|
+
respond_with(@payment) { |format| format.html { redirect_to new_admin_order_payment_path(@order) } }
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
data/app/models/spree/address.rb
CHANGED
@@ -8,6 +8,11 @@ module Spree
|
|
8
8
|
validates :firstname, :lastname, :address1, :city, :zipcode, :country, :phone, :presence => true
|
9
9
|
validate :state_validate
|
10
10
|
|
11
|
+
attr_accessible :firstname, :lastname, :address1, :address2,
|
12
|
+
:city, :zipcode, :country_id, :state_id,
|
13
|
+
:country, :state, :phone, :state_name,
|
14
|
+
:company, :alternative_phone
|
15
|
+
|
11
16
|
# disconnected since there's no code to display error messages yet OR matching client-side validation
|
12
17
|
def phone_validate
|
13
18
|
return if phone.blank?
|
@@ -60,7 +65,7 @@ module Spree
|
|
60
65
|
|
61
66
|
def self.default
|
62
67
|
country = Spree::Country.find_by_id(Spree::Config[:default_country_id])
|
63
|
-
new
|
68
|
+
new(:country => country || Country.first)
|
64
69
|
end
|
65
70
|
|
66
71
|
# can modify an address if it's not been used in an order (but checkouts controller has finer control)
|
@@ -22,6 +22,8 @@
|
|
22
22
|
#
|
23
23
|
module Spree
|
24
24
|
class Adjustment < ActiveRecord::Base
|
25
|
+
attr_accessible :amount, :label
|
26
|
+
|
25
27
|
belongs_to :adjustable, :polymorphic => true
|
26
28
|
belongs_to :source, :polymorphic => true
|
27
29
|
belongs_to :originator, :polymorphic => true
|
@@ -31,7 +33,7 @@ module Spree
|
|
31
33
|
|
32
34
|
scope :tax, lambda { where(:originator_type => 'Spree::TaxRate', :adjustable_type => 'Spree::Order') }
|
33
35
|
scope :price, lambda { where(:adjustable_type => 'Spree::LineItem') }
|
34
|
-
scope :shipping, lambda { where(:
|
36
|
+
scope :shipping, lambda { where(:originator_type => 'Spree::ShippingMethod') }
|
35
37
|
scope :optional, where(:mandatory => false)
|
36
38
|
scope :eligible, where(:eligible => true)
|
37
39
|
scope :charge, where("amount >= 0")
|
@@ -74,7 +76,7 @@ module Spree
|
|
74
76
|
private
|
75
77
|
|
76
78
|
def update_adjustable
|
77
|
-
adjustable.update! if adjustable.is_a? Order
|
79
|
+
adjustable.update! if adjustable.is_a? Spree::Order
|
78
80
|
end
|
79
81
|
|
80
82
|
end
|
@@ -1,7 +1,11 @@
|
|
1
|
+
require_dependency 'spree/calculator'
|
2
|
+
|
1
3
|
module Spree
|
2
4
|
class Calculator::FlatPercentItemTotal < Calculator
|
3
5
|
preference :flat_percent, :decimal, :default => 0
|
4
6
|
|
7
|
+
attr_accessible :preferred_flat_percent
|
8
|
+
|
5
9
|
def self.description
|
6
10
|
I18n.t(:flat_percent)
|
7
11
|
end
|
@@ -1,9 +1,13 @@
|
|
1
|
+
require_dependency 'spree/calculator'
|
2
|
+
|
1
3
|
module Spree
|
2
4
|
class Calculator::FlexiRate < Calculator
|
3
5
|
preference :first_item, :decimal, :default => 0.0
|
4
6
|
preference :additional_item, :decimal, :default => 0.0
|
5
7
|
preference :max_items, :integer, :default => 0
|
6
8
|
|
9
|
+
attr_accessible :preferred_first_item, :preferred_additional_item, :preferred_max_items
|
10
|
+
|
7
11
|
def self.description
|
8
12
|
I18n.t(:flexible_rate)
|
9
13
|
end
|
@@ -1,9 +1,15 @@
|
|
1
|
+
require_dependency 'spree/calculator'
|
2
|
+
|
1
3
|
module Spree
|
2
4
|
class Calculator::PriceSack < Calculator
|
3
5
|
preference :minimal_amount, :decimal, :default => 0
|
4
6
|
preference :normal_amount, :decimal, :default => 0
|
5
7
|
preference :discount_amount, :decimal, :default => 0
|
6
8
|
|
9
|
+
attr_accessible :preferred_minimal_amount,
|
10
|
+
:preferred_normal_amount,
|
11
|
+
:preferred_discount_amount
|
12
|
+
|
7
13
|
def self.description
|
8
14
|
I18n.t(:price_sack)
|
9
15
|
end
|
@@ -11,6 +11,9 @@ module Spree
|
|
11
11
|
validates :number, :presence => true, :unless => :has_payment_profile?, :on => :create
|
12
12
|
validates :verification_value, :presence => true, :unless => :has_payment_profile?, :on => :create
|
13
13
|
|
14
|
+
attr_accessible :first_name, :last_name, :number, :verification_value, :year,
|
15
|
+
:month, :gateway_customer_profile_id, :gateway_payment_profile_id
|
16
|
+
|
14
17
|
def process!(payment)
|
15
18
|
if Spree::Config[:auto_capture]
|
16
19
|
purchase(payment.amount.to_f, payment)
|
@@ -171,12 +174,12 @@ module Spree
|
|
171
174
|
record_log payment, response
|
172
175
|
|
173
176
|
if response.success?
|
174
|
-
Payment.create(:order => payment.order,
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
177
|
+
Payment.create({ :order => payment.order,
|
178
|
+
:source => payment,
|
179
|
+
:payment_method => payment.payment_method,
|
180
|
+
:amount => amount.abs * -1,
|
181
|
+
:response_code => response.authorization,
|
182
|
+
:state => 'completed'}, :without_protection => true)
|
180
183
|
else
|
181
184
|
gateway_error(response)
|
182
185
|
end
|
data/app/models/spree/gateway.rb
CHANGED
data/app/models/spree/image.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
module Spree
|
2
2
|
class Image < Asset
|
3
3
|
validate :no_attachment_errors
|
4
|
+
|
5
|
+
attr_accessible :alt, :attachment, :position, :viewable_type, :viewable_id
|
6
|
+
|
4
7
|
has_attached_file :attachment,
|
5
8
|
:styles => { :mini => '48x48>', :small => '100x100>', :product => '240x240>', :large => '600x600>' },
|
6
9
|
:default_style => :product,
|
@@ -16,6 +16,13 @@ module Spree
|
|
16
16
|
preference :mail_bcc, :string, :default => 'spree@example.com'
|
17
17
|
preference :intercept_email, :string, :default => nil
|
18
18
|
|
19
|
+
attr_accessible :environment, :preferred_enable_mail_delivery,
|
20
|
+
:preferred_mails_from, :preferred_mail_bcc,
|
21
|
+
:preferred_intercept_email, :preferred_mail_domain,
|
22
|
+
:preferred_mail_host, :preferred_mail_port,
|
23
|
+
:preferred_secure_connection_type, :preferred_mail_auth_type,
|
24
|
+
:preferred_smtp_username, :preferred_smtp_password
|
25
|
+
|
19
26
|
validates :environment, :presence => true
|
20
27
|
|
21
28
|
def self.current
|
@@ -4,6 +4,8 @@ module Spree
|
|
4
4
|
has_many :product_option_types, :dependent => :destroy
|
5
5
|
has_and_belongs_to_many :prototypes, :join_table => 'spree_option_types_prototypes'
|
6
6
|
|
7
|
+
attr_accessible :name, :presentation, :option_values_attributes
|
8
|
+
|
7
9
|
validates :name, :presentation, :presence => true
|
8
10
|
default_scope :order => "#{self.table_name}.position"
|
9
11
|
|
data/app/models/spree/order.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Spree
|
2
2
|
class Order < ActiveRecord::Base
|
3
3
|
attr_accessible :line_items, :bill_address_attributes, :ship_address_attributes, :payments_attributes,
|
4
|
-
:ship_address, :bill_address, :line_items_attributes,
|
4
|
+
:ship_address, :bill_address, :line_items_attributes, :number,
|
5
5
|
:shipping_method_id, :email, :use_billing, :special_instructions
|
6
6
|
|
7
7
|
belongs_to :user
|
data/app/models/spree/payment.rb
CHANGED
@@ -15,6 +15,8 @@ module Spree
|
|
15
15
|
attr_accessor :source_attributes
|
16
16
|
after_initialize :build_source
|
17
17
|
|
18
|
+
attr_accessible :amount, :payment_method_id, :source_attributes
|
19
|
+
|
18
20
|
scope :from_creditcard, where(:source_type => 'Spree::Creditcard')
|
19
21
|
scope :with_state, lambda { |s| where(:state => s) }
|
20
22
|
scope :completed, with_state('completed')
|
data/app/models/spree/product.rb
CHANGED
@@ -64,6 +64,14 @@ module Spree
|
|
64
64
|
|
65
65
|
validates :name, :price, :permalink, :presence => true
|
66
66
|
|
67
|
+
attr_accessible :name, :description, :available_on, :permalink, :meta_description,
|
68
|
+
:meta_keywords, :price, :sku, :deleted_at, :prototype_id,
|
69
|
+
:option_values_hash, :on_hand, :weight, :height, :width, :depth,
|
70
|
+
:shipping_category_id, :tax_category_id, :product_properties_attributes,
|
71
|
+
:variants_attributes, :taxon_ids
|
72
|
+
|
73
|
+
attr_accessible :cost_price if Variant.table_exists? && Variant.column_names.include?('cost_price')
|
74
|
+
|
67
75
|
accepts_nested_attributes_for :product_properties, :allow_destroy => true, :reject_if => lambda { |pp| pp[:property_name].blank? }
|
68
76
|
|
69
77
|
make_permalink
|
@@ -119,7 +127,7 @@ module Spree
|
|
119
127
|
def add_properties_and_option_types_from_prototype
|
120
128
|
if prototype_id && prototype = Spree::Prototype.find_by_id(prototype_id)
|
121
129
|
prototype.properties.each do |property|
|
122
|
-
product_properties.create(:property => property)
|
130
|
+
product_properties.create({:property => property}, :without_protection => true)
|
123
131
|
end
|
124
132
|
self.option_types = prototype.option_types
|
125
133
|
end
|
@@ -1,5 +1,14 @@
|
|
1
1
|
module Spree
|
2
2
|
class Product < ActiveRecord::Base
|
3
|
+
cattr_accessor :search_scopes do
|
4
|
+
[]
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.add_search_scope(name, &block)
|
8
|
+
self.singleton_class.send(:define_method, name.to_sym, &block)
|
9
|
+
search_scopes << name.to_sym
|
10
|
+
end
|
11
|
+
|
3
12
|
def self.simple_scopes
|
4
13
|
[
|
5
14
|
:ascend_by_updated_at,
|
@@ -22,37 +31,34 @@ module Spree
|
|
22
31
|
self.scope(name.to_s, relation.order(order_text))
|
23
32
|
end
|
24
33
|
|
25
|
-
|
34
|
+
add_search_scope :ascend_by_master_price do
|
26
35
|
joins(:variants_with_only_master).order("#{variant_table_name}.price ASC")
|
27
36
|
end
|
28
37
|
|
29
|
-
|
38
|
+
add_search_scope :descend_by_master_price do
|
30
39
|
joins(:variants_with_only_master).order("#{variant_table_name}.price DESC")
|
31
40
|
end
|
32
41
|
|
33
42
|
# Ryan Bates - http://railscasts.com/episodes/112
|
34
43
|
# general merging of conditions, names following the searchlogic pattern
|
35
|
-
|
44
|
+
add_search_scope :conditions do |*args|
|
45
|
+
where(args)
|
46
|
+
end
|
36
47
|
|
37
48
|
# conditions_all is a more descriptively named enhancement of the above
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
scope :conditions_any, lambda { |*args|
|
42
|
-
args = [args].flatten
|
43
|
-
raise "non-strings in conditions_any" unless args.all? { |s| s.is_a? String }
|
44
|
-
{ :conditions => args.map { |c| "(#{c})"}.join(" OR ") }
|
45
|
-
}
|
49
|
+
add_search_scope :conditions_all do |*args|
|
50
|
+
where([args].flatten)
|
51
|
+
end
|
46
52
|
|
47
|
-
|
53
|
+
add_search_scope :price_between do |low, high|
|
48
54
|
joins(:master).where(Variant.table_name => { :price => low..high })
|
49
55
|
end
|
50
56
|
|
51
|
-
|
57
|
+
add_search_scope :master_price_lte do |price|
|
52
58
|
joins(:master).where("#{variant_table_name}.price <= ?", price)
|
53
59
|
end
|
54
60
|
|
55
|
-
|
61
|
+
add_search_scope :master_price_gte do |price|
|
56
62
|
joins(:master).where("#{variant_table_name}.price >= ?", price)
|
57
63
|
end
|
58
64
|
|
@@ -60,7 +66,7 @@ module Spree
|
|
60
66
|
# If you need products only within one taxon use
|
61
67
|
#
|
62
68
|
# Spree::Product.taxons_id_eq(x)
|
63
|
-
|
69
|
+
add_search_scope :in_taxon do |taxon|
|
64
70
|
joins(:taxons).where(Taxon.table_name => { :id => taxon.self_and_descendants.map(&:id) })
|
65
71
|
end
|
66
72
|
|
@@ -68,8 +74,7 @@ module Spree
|
|
68
74
|
# If you need products only within one taxon use
|
69
75
|
#
|
70
76
|
# Spree::Product.taxons_id_eq([x,y])
|
71
|
-
|
72
|
-
def self.in_taxons(*taxons)
|
77
|
+
add_search_scope :in_taxons do |*taxons|
|
73
78
|
taxons = get_taxons(taxons)
|
74
79
|
taxons.first ? prepare_taxon_conditions(taxons) : scoped
|
75
80
|
end
|
@@ -79,7 +84,7 @@ module Spree
|
|
79
84
|
end
|
80
85
|
|
81
86
|
# a scope that finds all products having property specified by name, object or id
|
82
|
-
|
87
|
+
add_search_scope :with_property do |property|
|
83
88
|
properties = Property.table_name
|
84
89
|
conditions = case property
|
85
90
|
when String then { "#{properties}.name" => property }
|
@@ -92,7 +97,7 @@ module Spree
|
|
92
97
|
|
93
98
|
# a simple test for product with a certain property-value pairing
|
94
99
|
# note that it can test for properties with NULL values, but not for absent values
|
95
|
-
|
100
|
+
add_search_scope :with_property_value do |property, value|
|
96
101
|
properties = Spree::Property.table_name
|
97
102
|
conditions = case property
|
98
103
|
when String then ["#{properties}.name = ?", property]
|
@@ -104,8 +109,7 @@ module Spree
|
|
104
109
|
joins(:properties).where(conditions)
|
105
110
|
end
|
106
111
|
|
107
|
-
|
108
|
-
def self.with_option(option)
|
112
|
+
add_search_scope :with_option do |option|
|
109
113
|
option_types = OptionType.table_name
|
110
114
|
conditions = case option
|
111
115
|
when String then { "#{option_types}.name" => option }
|
@@ -116,8 +120,7 @@ module Spree
|
|
116
120
|
joins(:option_types).where(conditions)
|
117
121
|
end
|
118
122
|
|
119
|
-
|
120
|
-
def self.with_option_value(option, value)
|
123
|
+
add_search_scope :with_option_value do |option, value|
|
121
124
|
option_values = OptionValue.table_name
|
122
125
|
option_type_id = case option
|
123
126
|
when String then OptionType.find_by_name(option) || option.to_i
|
@@ -132,30 +135,30 @@ module Spree
|
|
132
135
|
# Finds all products which have either:
|
133
136
|
# 1) have an option value with the name matching the one given
|
134
137
|
# 2) have a product property with a value matching the one given
|
135
|
-
|
138
|
+
add_search_scope :with do |value|
|
136
139
|
includes(:variants_including_master => :option_values).
|
137
140
|
includes(:product_properties).
|
138
141
|
where("#{OptionValue.table_name}.name = ? OR #{ProductProperty.table_name}.value = ?", value, value)
|
139
142
|
end
|
140
143
|
|
141
144
|
# Finds all products that have a name containing the given words.
|
142
|
-
|
145
|
+
add_search_scope :in_name do |words|
|
143
146
|
like_any([:name], prepare_words(words))
|
144
147
|
end
|
145
148
|
|
146
149
|
# Finds all products that have a name or meta_keywords containing the given words.
|
147
|
-
|
150
|
+
add_search_scope :in_name_or_keywords do |words|
|
148
151
|
like_any([:name, :meta_keywords], prepare_words(words))
|
149
152
|
end
|
150
153
|
|
151
154
|
# Finds all products that have a name, description, meta_description or meta_keywords containing the given keywords.
|
152
|
-
|
155
|
+
add_search_scope :in_name_or_description do |words|
|
153
156
|
like_any([:name, :description, :meta_description, :meta_keywords], prepare_words(words))
|
154
157
|
end
|
155
158
|
|
156
159
|
# Finds all products that have the ids matching the given collection of ids.
|
157
160
|
# Alternatively, you could use find(collection_of_ids), but that would raise an exception if one product couldn't be found
|
158
|
-
|
161
|
+
add_search_scope :with_ids do |*ids|
|
159
162
|
where(:id => ids)
|
160
163
|
end
|
161
164
|
|
@@ -167,7 +170,7 @@ module Spree
|
|
167
170
|
#
|
168
171
|
# :joins => "LEFT OUTER JOIN (SELECT line_items.variant_id as vid, COUNT(*) as cnt FROM line_items GROUP BY line_items.variant_id) AS popularity_count ON variants.id = vid",
|
169
172
|
# :order => 'COALESCE(cnt, 0) DESC'
|
170
|
-
|
173
|
+
add_search_scope :descend_by_popularity do
|
171
174
|
joins(:master).
|
172
175
|
order(%Q{
|
173
176
|
COALESCE((
|
@@ -185,25 +188,26 @@ module Spree
|
|
185
188
|
})
|
186
189
|
end
|
187
190
|
|
188
|
-
|
191
|
+
add_search_scope :not_deleted do
|
189
192
|
where(:deleted_at => nil)
|
190
193
|
end
|
191
194
|
|
195
|
+
# Can't use add_search_scope for this as it needs a default argument
|
192
196
|
def self.available(available_on = nil)
|
193
197
|
where('available_on <= ?', available_on || Time.now)
|
194
198
|
end
|
199
|
+
search_scopes << :available
|
195
200
|
|
196
|
-
|
197
|
-
def self.active
|
201
|
+
add_search_scope :active do
|
198
202
|
not_deleted.available
|
199
203
|
end
|
200
204
|
|
201
|
-
|
205
|
+
add_search_scope :on_hand do
|
202
206
|
variants_table = Variant.table_name
|
203
207
|
where("#{table_name}.id in (select product_id from #{variants_table} where product_id = #{table_name}.id group by product_id having sum(count_on_hand) > 0)")
|
204
208
|
end
|
205
209
|
|
206
|
-
|
210
|
+
add_search_scope :taxons_name_eq do |name|
|
207
211
|
joins(:taxons).where(Taxon.arel_table[:name].eq(name))
|
208
212
|
end
|
209
213
|
|
@@ -215,6 +219,7 @@ module Spree
|
|
215
219
|
scope :group_by_products_id, { :group => "#{self.quoted_table_name}.id" }
|
216
220
|
end
|
217
221
|
search_methods :group_by_products_id
|
222
|
+
search_scopes << :group_by_products_id
|
218
223
|
|
219
224
|
private
|
220
225
|
def self.variant_table_name
|