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