spree_core 1.3.1 → 1.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/app/assets/javascripts/admin/admin.js.erb +1 -1
- data/app/assets/javascripts/admin/shipping_methods.js.coffee +1 -1
- data/app/assets/javascripts/admin/spree_core.js +1 -0
- data/app/assets/javascripts/admin/variant_autocomplete.js.erb +1 -1
- data/app/assets/stylesheets/admin/globals/_variables.scss +7 -7
- data/app/assets/stylesheets/admin/plugins/font-awesome.scss +2 -2
- data/app/assets/stylesheets/admin/shared/_forms.scss +19 -16
- data/app/assets/stylesheets/admin/shared/_layout.scss +1 -1
- data/app/assets/stylesheets/admin/shared/_typography.scss +10 -10
- data/app/assets/stylesheets/store/screen.css.scss +50 -50
- data/app/controllers/spree/admin/base_controller.rb +0 -1
- data/app/controllers/spree/admin/images_controller.rb +1 -1
- data/app/controllers/spree/admin/line_items_controller.rb +1 -0
- data/app/controllers/spree/admin/orders_controller.rb +5 -1
- data/app/controllers/spree/admin/payments_controller.rb +2 -1
- data/app/controllers/spree/admin/products_controller.rb +3 -1
- data/app/controllers/spree/admin/resource_controller.rb +15 -4
- data/app/controllers/spree/admin/shipments_controller.rb +6 -1
- data/app/controllers/spree/admin/taxons_controller.rb +0 -6
- data/app/controllers/spree/checkout_controller.rb +0 -4
- data/app/controllers/spree/locale_controller.rb +2 -2
- data/app/controllers/spree/orders_controller.rb +1 -1
- data/app/helpers/spree/admin/base_helper.rb +9 -1
- data/app/helpers/spree/admin/images_helper.rb +14 -0
- data/app/helpers/spree/admin/products_helper.rb +1 -1
- data/app/helpers/spree/base_helper.rb +3 -3
- data/app/models/spree/ability.rb +2 -6
- data/app/models/spree/address.rb +6 -1
- data/app/models/spree/legacy_user.rb +11 -0
- data/app/models/spree/log_entry.rb +11 -0
- data/app/models/spree/order.rb +11 -5
- data/app/models/spree/order_populator.rb +2 -2
- data/app/models/spree/order_updater.rb +11 -11
- data/app/models/spree/payment/processing.rb +2 -2
- data/app/models/spree/payment.rb +20 -1
- data/app/models/spree/payment_method.rb +10 -3
- data/app/models/spree/preference.rb +0 -29
- data/app/models/spree/preferences/store.rb +4 -10
- data/app/models/spree/product/scopes.rb +2 -2
- data/app/models/spree/product.rb +2 -5
- data/app/models/spree/product_property.rb +3 -1
- data/app/models/spree/property.rb +0 -2
- data/app/models/spree/return_authorization.rb +1 -1
- data/app/models/spree/shipment.rb +1 -1
- data/app/models/spree/variant.rb +1 -1
- data/app/views/spree/admin/general_settings/edit.html.erb +2 -2
- data/app/views/spree/admin/images/index.html.erb +6 -33
- data/app/views/spree/admin/orders/_form.html.erb +1 -1
- data/app/views/spree/admin/payment_methods/_form.html.erb +4 -0
- data/app/views/spree/admin/payment_methods/index.html.erb +3 -1
- data/app/views/spree/admin/product_properties/_product_property_fields.html.erb +5 -1
- data/app/views/spree/admin/product_properties/index.html.erb +2 -2
- data/app/views/spree/admin/products/_form.html.erb +1 -6
- data/app/views/spree/admin/products/edit.html.erb +4 -1
- data/app/views/spree/admin/prototypes/_form.html.erb +1 -1
- data/app/views/spree/admin/prototypes/select.js.erb +2 -2
- data/app/views/spree/admin/return_authorizations/index.html.erb +1 -1
- data/app/views/spree/admin/shared/_tabs.html.erb +1 -1
- data/app/views/spree/admin/shared/_translations.html.erb +1 -1
- data/app/views/spree/admin/shipments/_form.html.erb +1 -1
- data/app/views/spree/admin/shipping_methods/_form.html.erb +3 -3
- data/app/views/spree/admin/taxonomies/get_children.json.erb +1 -1
- data/app/views/spree/admin/variants/_autocomplete.js.erb +1 -1
- data/app/views/spree/shared/_order_details.html.erb +1 -1
- data/config/routes.rb +5 -1
- data/db/migrate/20121031162139_split_prices_from_variants.rb +1 -1
- data/db/migrate/20130114053446_add_display_on_to_spree_payment_methods.rb +9 -0
- data/db/migrate/20130120201805_add_position_to_product_properties.spree.rb +6 -0
- data/db/migrate/20130203232234_add_identifier_to_spree_payments.rb +5 -0
- data/lib/generators/spree/install/install_generator.rb +4 -1
- data/lib/spree/core/controller_helpers/common.rb +3 -3
- data/lib/spree/core/controller_helpers.rb +13 -0
- data/lib/spree/core/engine.rb +7 -4
- data/lib/spree/core/permalinks.rb +1 -1
- data/lib/spree/core/ssl_requirement.rb +1 -1
- data/lib/spree/core/testing_support/authorization_helpers.rb +5 -2
- data/lib/spree/core/testing_support/bar_ability.rb +17 -0
- data/lib/spree/core/testing_support/factories/product_factory.rb +4 -2
- data/lib/spree/core/testing_support/factories/variant_factory.rb +9 -3
- data/lib/spree/core/testing_support/preferences.rb +12 -6
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +1 -1
- data/lib/spree/scopes/dynamic.rb +1 -1
- data/lib/tasks/core.rake +3 -3
- data/vendor/assets/javascripts/jquery-migrate-1.0.0.js +498 -0
- metadata +14 -7
@@ -77,7 +77,7 @@ module Spree
|
|
77
77
|
|
78
78
|
def load_data
|
79
79
|
@amount = params[:amount] || load_order.total
|
80
|
-
@payment_methods = PaymentMethod.available
|
80
|
+
@payment_methods = PaymentMethod.available(:back_end)
|
81
81
|
if @payment and @payment.payment_method
|
82
82
|
@payment_method = @payment.payment_method
|
83
83
|
else
|
@@ -88,6 +88,7 @@ module Spree
|
|
88
88
|
|
89
89
|
def load_order
|
90
90
|
@order = Order.find_by_number!(params[:order_id])
|
91
|
+
authorize! params[:action], @order
|
91
92
|
end
|
92
93
|
|
93
94
|
def load_payment
|
@@ -9,10 +9,12 @@ module Spree
|
|
9
9
|
update.before :update_before
|
10
10
|
|
11
11
|
def show
|
12
|
+
session[:return_to] ||= request.referer
|
12
13
|
redirect_to( :action => :edit )
|
13
14
|
end
|
14
15
|
|
15
16
|
def index
|
17
|
+
session[:return_to] = request.url
|
16
18
|
respond_with(@collection)
|
17
19
|
end
|
18
20
|
|
@@ -33,7 +35,7 @@ module Spree
|
|
33
35
|
end
|
34
36
|
|
35
37
|
def destroy
|
36
|
-
@product = Product.
|
38
|
+
@product = Product.find_by_permalink!(params[:id])
|
37
39
|
@product.delete
|
38
40
|
|
39
41
|
flash.notice = I18n.t('notice_messages.product_deleted')
|
@@ -40,6 +40,7 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
40
40
|
|
41
41
|
def create
|
42
42
|
invoke_callbacks(:create, :before)
|
43
|
+
@object.attributes = params[object_name]
|
43
44
|
if @object.save
|
44
45
|
invoke_callbacks(:create, :after)
|
45
46
|
flash[:success] = flash_message_for(@object, :successfully_created)
|
@@ -134,9 +135,19 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
134
135
|
def load_resource
|
135
136
|
if member_action?
|
136
137
|
@object ||= load_resource_instance
|
138
|
+
|
139
|
+
# call authorize! a third time (called twice already in Admin::BaseController)
|
140
|
+
# this time we pass the actual instance so fine-grained abilities can control
|
141
|
+
# access to individual records, not just entire models.
|
142
|
+
authorize! params[:action], @object
|
143
|
+
|
137
144
|
instance_variable_set("@#{object_name}", @object)
|
138
145
|
else
|
139
146
|
@collection ||= collection
|
147
|
+
|
148
|
+
# note: we don't call authorize here as the collection method should use
|
149
|
+
# CanCan's accessible_by method to restrict the actual records returned
|
150
|
+
|
140
151
|
instance_variable_set("@#{controller_name}", @collection)
|
141
152
|
end
|
142
153
|
end
|
@@ -155,7 +166,7 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
155
166
|
|
156
167
|
def parent
|
157
168
|
if parent_data.present?
|
158
|
-
@parent ||= parent_data[:model_class].
|
169
|
+
@parent ||= parent_data[:model_class].send("find_by_#{parent_data[:find_by]}", params["#{model_name}_id"])
|
159
170
|
instance_variable_set("@#{model_name}", @parent)
|
160
171
|
else
|
161
172
|
nil
|
@@ -172,16 +183,16 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
|
|
172
183
|
|
173
184
|
def build_resource
|
174
185
|
if parent_data.present?
|
175
|
-
parent.send(controller_name).build
|
186
|
+
parent.send(controller_name).build
|
176
187
|
else
|
177
|
-
model_class.new
|
188
|
+
model_class.new
|
178
189
|
end
|
179
190
|
end
|
180
191
|
|
181
192
|
def collection
|
182
193
|
return parent.send(controller_name) if parent_data.present?
|
183
194
|
if model_class.respond_to?(:accessible_by) && !current_ability.has_block?(params[:action], model_class)
|
184
|
-
model_class.accessible_by(current_ability)
|
195
|
+
model_class.accessible_by(current_ability, params[:action])
|
185
196
|
else
|
186
197
|
model_class.scoped
|
187
198
|
end
|
@@ -79,10 +79,11 @@ module Spree
|
|
79
79
|
|
80
80
|
def order
|
81
81
|
@order ||= Order.find_by_number(params[:order_id])
|
82
|
+
authorize! params[:action], @order
|
82
83
|
end
|
83
84
|
|
84
85
|
def shipment
|
85
|
-
@shipment ||=
|
86
|
+
@shipment ||= order.shipments.find_by_number(params[:id])
|
86
87
|
end
|
87
88
|
|
88
89
|
def build_shipment
|
@@ -92,6 +93,10 @@ module Spree
|
|
92
93
|
@shipment.shipping_method ||= order.shipping_method
|
93
94
|
@shipment.attributes = params[:shipment]
|
94
95
|
end
|
96
|
+
|
97
|
+
def model_class
|
98
|
+
Spree::Shipment
|
99
|
+
end
|
95
100
|
end
|
96
101
|
end
|
97
102
|
end
|
@@ -107,10 +107,6 @@ module Spree
|
|
107
107
|
@order.shipping_method ||= (@order.rate_hash.first && @order.rate_hash.first[:shipping_method])
|
108
108
|
end
|
109
109
|
|
110
|
-
def before_payment
|
111
|
-
current_order.payments.destroy_all if request.put?
|
112
|
-
end
|
113
|
-
|
114
110
|
def after_complete
|
115
111
|
session[:order_id] = nil
|
116
112
|
end
|
@@ -4,8 +4,8 @@ module Spree
|
|
4
4
|
if request.referer && request.referer.starts_with?('http://' + request.host)
|
5
5
|
session['user_return_to'] = request.referer
|
6
6
|
end
|
7
|
-
if params[:locale] && I18n.available_locales.include?(params[:locale]
|
8
|
-
session[:locale] = I18n.locale = params[:locale]
|
7
|
+
if params[:locale] && I18n.available_locales.map(&:to_s).include?(params[:locale])
|
8
|
+
session[:locale] = I18n.locale = params[:locale]
|
9
9
|
flash.notice = t(:locale_changed)
|
10
10
|
else
|
11
11
|
flash[:error] = t(:locale_not_changed)
|
@@ -40,7 +40,7 @@ module Spree
|
|
40
40
|
|
41
41
|
# Adds a new item to the order (creating a new order if none already exists)
|
42
42
|
def populate
|
43
|
-
populator = OrderPopulator.new(current_order(true), current_currency)
|
43
|
+
populator = Spree::OrderPopulator.new(current_order(true), current_currency)
|
44
44
|
if populator.populate(params.slice(:products, :variants, :quantity))
|
45
45
|
fire_event('spree.cart.add')
|
46
46
|
fire_event('spree.order.contents_changed')
|
@@ -22,6 +22,14 @@ module Spree
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def datepicker_field_value(date)
|
26
|
+
unless date.blank?
|
27
|
+
l(date, :format => t('spree.date_picker.format'))
|
28
|
+
else
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
25
33
|
# This method demonstrates the use of the :child_index option to render a
|
26
34
|
# form partial for, for instance, client side addition of new nested
|
27
35
|
# records.
|
@@ -54,7 +62,7 @@ module Spree
|
|
54
62
|
def remove_nested(fields)
|
55
63
|
out = ''
|
56
64
|
out << fields.hidden_field(:_destroy) unless fields.object.new_record?
|
57
|
-
out << (link_to icon('
|
65
|
+
out << (link_to icon('icon-remove'), "#", :class => 'remove')
|
58
66
|
out.html_safe
|
59
67
|
end
|
60
68
|
|
@@ -13,7 +13,7 @@ module Spree
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def link_to_cart(text = nil)
|
16
|
-
return "" if current_spree_page?(cart_path)
|
16
|
+
return "" if current_spree_page?(spree.cart_path)
|
17
17
|
|
18
18
|
text = text ? h(text) : t('cart')
|
19
19
|
css_class = nil
|
@@ -26,7 +26,7 @@ module Spree
|
|
26
26
|
css_class = 'full'
|
27
27
|
end
|
28
28
|
|
29
|
-
link_to text, cart_path, :class => css_class
|
29
|
+
link_to text, spree.cart_path, :class => css_class
|
30
30
|
end
|
31
31
|
|
32
32
|
# human readable list of variant options
|
@@ -127,7 +127,7 @@ module Spree
|
|
127
127
|
end
|
128
128
|
|
129
129
|
countries.collect do |country|
|
130
|
-
country.name = I18n.t(country.iso, :scope => '
|
130
|
+
country.name = I18n.t(country.iso, :scope => 'country_names', :default => country.name)
|
131
131
|
country
|
132
132
|
end.sort { |a, b| a.name <=> b.name }
|
133
133
|
end
|
data/app/models/spree/ability.rb
CHANGED
@@ -30,18 +30,14 @@ module Spree
|
|
30
30
|
alias_action :new, :to => :create
|
31
31
|
alias_action :new_action, :to => :create
|
32
32
|
alias_action :show, :to => :read
|
33
|
+
alias_action :delete, :to => :destroy
|
33
34
|
|
34
35
|
user ||= Spree.user_class.new
|
35
36
|
if user.respond_to?(:has_spree_role?) && user.has_spree_role?('admin')
|
36
37
|
can :manage, :all
|
37
38
|
else
|
38
39
|
#############################
|
39
|
-
can :read, Spree.user_class
|
40
|
-
resource == user
|
41
|
-
end
|
42
|
-
can :update, Spree.user_class do |resource|
|
43
|
-
resource == user
|
44
|
-
end
|
40
|
+
can [:read,:update,:destroy], Spree.user_class, :id => user.id
|
45
41
|
can :create, Spree.user_class
|
46
42
|
#############################
|
47
43
|
can :read, Order do |order, token|
|
data/app/models/spree/address.rb
CHANGED
@@ -5,7 +5,8 @@ module Spree
|
|
5
5
|
|
6
6
|
has_many :shipments
|
7
7
|
|
8
|
-
validates :firstname, :lastname, :address1, :city, :zipcode, :country, :
|
8
|
+
validates :firstname, :lastname, :address1, :city, :zipcode, :country, :presence => true
|
9
|
+
validates :phone, :presence => true, :if => :require_phone?
|
9
10
|
validate :state_validate
|
10
11
|
|
11
12
|
attr_accessible :firstname, :lastname, :address1, :address2,
|
@@ -83,6 +84,10 @@ module Spree
|
|
83
84
|
|
84
85
|
private
|
85
86
|
|
87
|
+
def require_phone?
|
88
|
+
true
|
89
|
+
end
|
90
|
+
|
86
91
|
def state_validate
|
87
92
|
# Skip state validation without country (also required)
|
88
93
|
# or when disabled by preference
|
@@ -4,11 +4,16 @@ module Spree
|
|
4
4
|
self.table_name = 'spree_users'
|
5
5
|
attr_accessible :email, :password, :password_confirmation
|
6
6
|
|
7
|
+
has_many :orders, :foreign_key => :user_id
|
7
8
|
belongs_to :ship_address, :class_name => 'Spree::Address'
|
8
9
|
belongs_to :bill_address, :class_name => 'Spree::Address'
|
9
10
|
|
10
11
|
scope :registered
|
11
12
|
|
13
|
+
before_destroy :check_completed_orders
|
14
|
+
|
15
|
+
class DestroyWithOrdersError < StandardError; end
|
16
|
+
|
12
17
|
def anonymous?
|
13
18
|
false
|
14
19
|
end
|
@@ -24,5 +29,11 @@ module Spree
|
|
24
29
|
|
25
30
|
attr_accessor :password
|
26
31
|
attr_accessor :password_confirmation
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def check_completed_orders
|
36
|
+
raise DestroyWithOrdersError if orders.complete.present?
|
37
|
+
end
|
27
38
|
end
|
28
39
|
end
|
@@ -1,5 +1,16 @@
|
|
1
1
|
module Spree
|
2
2
|
class LogEntry < ActiveRecord::Base
|
3
3
|
belongs_to :source, :polymorphic => true
|
4
|
+
|
5
|
+
# Fix for #1767
|
6
|
+
# If a payment fails, we want to make sure we keep the record of it failing
|
7
|
+
after_rollback :save_anyway
|
8
|
+
|
9
|
+
def save_anyway
|
10
|
+
log = Spree::LogEntry.new
|
11
|
+
log.source = source
|
12
|
+
log.details = details
|
13
|
+
log.save!
|
14
|
+
end
|
4
15
|
end
|
5
16
|
end
|
data/app/models/spree/order.rb
CHANGED
@@ -31,7 +31,7 @@ module Spree
|
|
31
31
|
token_resource
|
32
32
|
|
33
33
|
attr_accessible :line_items, :bill_address_attributes, :ship_address_attributes, :payments_attributes,
|
34
|
-
:ship_address, :bill_address, :line_items_attributes, :number,
|
34
|
+
:ship_address, :bill_address, :payments_attributes, :line_items_attributes, :number,
|
35
35
|
:shipping_method_id, :email, :use_billing, :special_instructions, :currency
|
36
36
|
|
37
37
|
if Spree.user_class
|
@@ -52,7 +52,13 @@ module Spree
|
|
52
52
|
has_many :line_items, :dependent => :destroy, :order => "created_at ASC"
|
53
53
|
has_many :inventory_units
|
54
54
|
has_many :payments, :dependent => :destroy
|
55
|
-
|
55
|
+
|
56
|
+
has_many :shipments, :dependent => :destroy do
|
57
|
+
def states
|
58
|
+
pluck(:state).uniq
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
56
62
|
has_many :return_authorizations, :dependent => :destroy
|
57
63
|
has_many :adjustments, :as => :adjustable, :dependent => :destroy, :order => "created_at ASC"
|
58
64
|
|
@@ -351,11 +357,11 @@ module Spree
|
|
351
357
|
end
|
352
358
|
|
353
359
|
def can_ship?
|
354
|
-
self.complete? || self.resumed?
|
360
|
+
self.complete? || self.resumed? || self.awaiting_return? || self.returned?
|
355
361
|
end
|
356
362
|
|
357
363
|
def credit_cards
|
358
|
-
credit_card_ids = payments.from_credit_card.
|
364
|
+
credit_card_ids = payments.from_credit_card.pluck(:source_id).uniq
|
359
365
|
CreditCard.scoped(:conditions => { :id => credit_card_ids })
|
360
366
|
end
|
361
367
|
|
@@ -436,7 +442,7 @@ module Spree
|
|
436
442
|
end
|
437
443
|
|
438
444
|
def available_payment_methods
|
439
|
-
@available_payment_methods ||= PaymentMethod.available
|
445
|
+
@available_payment_methods ||= PaymentMethod.available(:front_end)
|
440
446
|
end
|
441
447
|
|
442
448
|
def payment_method
|
@@ -50,9 +50,9 @@ module Spree
|
|
50
50
|
display_name = %Q{#{variant.name}}
|
51
51
|
display_name += %Q{ (#{variant.options_text})} unless variant.options_text.blank?
|
52
52
|
|
53
|
-
if variant.
|
53
|
+
if variant.available?
|
54
54
|
on_hand = variant.on_hand
|
55
|
-
if on_hand >= quantity
|
55
|
+
if on_hand >= quantity || Spree::Config[:allow_backorders]
|
56
56
|
return true
|
57
57
|
else
|
58
58
|
errors.add(:base, %Q{There are only #{on_hand} of #{display_name.inspect} remaining.} +
|
@@ -69,18 +69,18 @@ module Spree
|
|
69
69
|
if order.backordered?
|
70
70
|
order.shipment_state = 'backorder'
|
71
71
|
else
|
72
|
-
order
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
'shipped'
|
78
|
-
when shipments.ready.count
|
79
|
-
'ready'
|
80
|
-
when shipments.pending.count
|
81
|
-
'pending'
|
72
|
+
# get all the shipment states for this order
|
73
|
+
shipment_states = shipments.states
|
74
|
+
if shipment_states.size > 1
|
75
|
+
# multiple shiment states means it's most likely partially shipped
|
76
|
+
order.shipment_state = 'partial'
|
82
77
|
else
|
83
|
-
|
78
|
+
# will return nil if no shipments are found
|
79
|
+
order.shipment_state = shipment_states.first
|
80
|
+
if order.shipment_state && order.inventory_units.where(:shipment_id => nil).exists?
|
81
|
+
# shipments exist but there are unassigned inventory units
|
82
|
+
order.shipment_state = 'partial'
|
83
|
+
end
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -5,7 +5,7 @@ module Spree
|
|
5
5
|
if payment_method && payment_method.source_required?
|
6
6
|
if source
|
7
7
|
if !processing?
|
8
|
-
if
|
8
|
+
if payment_method.auto_capture?
|
9
9
|
purchase!
|
10
10
|
else
|
11
11
|
authorize!
|
@@ -111,7 +111,7 @@ module Spree
|
|
111
111
|
options = { :email => order.email,
|
112
112
|
:customer => order.email,
|
113
113
|
:ip => order.last_ip_address,
|
114
|
-
:order_id => order.number }
|
114
|
+
:order_id => "#{order.number}-#{self.identifier}" }
|
115
115
|
|
116
116
|
options.merge!({ :shipping => order.ship_total * 100,
|
117
117
|
:tax => order.tax_total * 100,
|
data/app/models/spree/payment.rb
CHANGED
@@ -8,6 +8,8 @@ module Spree
|
|
8
8
|
has_many :offsets, :class_name => "Spree::Payment", :foreign_key => :source_id, :conditions => "source_type = 'Spree::Payment' AND amount < 0 AND state = 'completed'"
|
9
9
|
has_many :log_entries, :as => :source
|
10
10
|
|
11
|
+
before_save :set_unique_identifier
|
12
|
+
|
11
13
|
after_save :create_payment_profile, :if => :profiles_supported?
|
12
14
|
|
13
15
|
# update the order totals, etc.
|
@@ -56,7 +58,7 @@ module Spree
|
|
56
58
|
end
|
57
59
|
|
58
60
|
def offsets_total
|
59
|
-
offsets.
|
61
|
+
offsets.pluck(:amount).sum
|
60
62
|
end
|
61
63
|
|
62
64
|
def credit_allowed
|
@@ -108,5 +110,22 @@ module Spree
|
|
108
110
|
order.payments.reload
|
109
111
|
order.update!
|
110
112
|
end
|
113
|
+
|
114
|
+
# Necessary because some payment gateways will refuse payments with
|
115
|
+
# duplicate IDs. We *were* using the Order number, but that's set once and
|
116
|
+
# is unchanging. What we need is a unique identifier on a per-payment basis,
|
117
|
+
# and this is it. Related to #1998.
|
118
|
+
# See https://github.com/spree/spree/issues/1998#issuecomment-12869105
|
119
|
+
def set_unique_identifier
|
120
|
+
chars = [('A'..'Z').to_a, ('0'..'9').to_a].flatten - %w(0 1 I O)
|
121
|
+
identifier = ''
|
122
|
+
8.times { identifier << chars[rand(chars.length)] }
|
123
|
+
if Spree::Payment.exists?(:identifier => identifier)
|
124
|
+
# Call it again, we've got a duplicate ID.
|
125
|
+
set_unique_identifier
|
126
|
+
else
|
127
|
+
self.identifier = identifier
|
128
|
+
end
|
129
|
+
end
|
111
130
|
end
|
112
131
|
end
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Spree
|
2
2
|
class PaymentMethod < ActiveRecord::Base
|
3
|
+
DISPLAY = [:both, :front_end, :back_end]
|
3
4
|
default_scope where(:deleted_at => nil)
|
4
5
|
|
5
6
|
scope :production, lambda { where(:environment => 'production') }
|
6
7
|
|
7
|
-
attr_accessible :name, :description, :environment, :active
|
8
|
+
attr_accessible :name, :description, :environment, :display_on, :active
|
8
9
|
validates :name, :presence => true
|
9
10
|
|
10
11
|
def self.providers
|
@@ -22,9 +23,11 @@ module Spree
|
|
22
23
|
raise 'You must implement payment_source_class method for this gateway.'
|
23
24
|
end
|
24
25
|
|
25
|
-
def self.available
|
26
|
+
def self.available(display_on = 'both')
|
26
27
|
all.select do |p|
|
27
|
-
p.active &&
|
28
|
+
p.active &&
|
29
|
+
(p.display_on == display_on.to_s || p.display_on.blank?) &&
|
30
|
+
(p.environment == Rails.env || p.environment.blank?)
|
28
31
|
end
|
29
32
|
end
|
30
33
|
|
@@ -51,5 +54,9 @@ module Spree
|
|
51
54
|
def source_required?
|
52
55
|
true
|
53
56
|
end
|
57
|
+
|
58
|
+
def auto_capture?
|
59
|
+
Spree::Config[:auto_capture]
|
60
|
+
end
|
54
61
|
end
|
55
62
|
end
|
@@ -33,33 +33,4 @@ class Spree::Preference < ActiveRecord::Base
|
|
33
33
|
self[:value]
|
34
34
|
end
|
35
35
|
|
36
|
-
# For the rc releases of 1.0, we stored the object class names, this converts
|
37
|
-
# to preferences definition types. This code should eventually be removed.
|
38
|
-
# it is called during the load_preferences of the Preferences::Store
|
39
|
-
def self.convert_old_value_types(preference)
|
40
|
-
classes = [Symbol.to_s, Fixnum.to_s, Bignum.to_s,
|
41
|
-
Float.to_s, TrueClass.to_s, FalseClass.to_s]
|
42
|
-
return unless classes.map(&:downcase).include? preference.value_type.downcase
|
43
|
-
|
44
|
-
case preference.value_type.downcase
|
45
|
-
when "symbol"
|
46
|
-
preference.value_type = 'string'
|
47
|
-
when "fixnum"
|
48
|
-
preference.value_type = 'integer'
|
49
|
-
when "bignum"
|
50
|
-
preference.value_type = 'integer'
|
51
|
-
preference.value = preference.value.to_f.to_i
|
52
|
-
when "float"
|
53
|
-
preference.value_type = 'decimal'
|
54
|
-
when "trueclass"
|
55
|
-
preference.value_type = 'boolean'
|
56
|
-
preference.value = "true"
|
57
|
-
when "falseclass"
|
58
|
-
preference.value_type = 'boolean'
|
59
|
-
preference.value = "false"
|
60
|
-
end
|
61
|
-
|
62
|
-
preference.save
|
63
|
-
end
|
64
|
-
|
65
36
|
end
|
@@ -14,7 +14,6 @@ module Spree::Preferences
|
|
14
14
|
def initialize
|
15
15
|
@cache = Rails.cache
|
16
16
|
@persistence = true
|
17
|
-
load_preferences
|
18
17
|
end
|
19
18
|
|
20
19
|
def set(key, value, type)
|
@@ -64,6 +63,10 @@ module Spree::Preferences
|
|
64
63
|
destroy(key)
|
65
64
|
end
|
66
65
|
|
66
|
+
def clear_cache
|
67
|
+
@cache.clear
|
68
|
+
end
|
69
|
+
|
67
70
|
private
|
68
71
|
|
69
72
|
def persist(cache_key, value, type)
|
@@ -82,15 +85,6 @@ module Spree::Preferences
|
|
82
85
|
preference.destroy if preference
|
83
86
|
end
|
84
87
|
|
85
|
-
def load_preferences
|
86
|
-
return unless should_persist?
|
87
|
-
|
88
|
-
Spree::Preference.valid.each do |p|
|
89
|
-
Spree::Preference.convert_old_value_types(p) # see comment
|
90
|
-
@cache.write(p.key, p.value)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
88
|
def should_persist?
|
95
89
|
@persistence and Spree::Preference.table_exists?
|
96
90
|
end
|
@@ -66,7 +66,7 @@ module Spree
|
|
66
66
|
add_search_scope :in_taxon do |taxon|
|
67
67
|
select("DISTINCT(spree_products.id), spree_products.*").
|
68
68
|
joins(:taxons).
|
69
|
-
where(Taxon.table_name => { :id => taxon.self_and_descendants.
|
69
|
+
where(Taxon.table_name => { :id => taxon.self_and_descendants.pluck(:id) })
|
70
70
|
end
|
71
71
|
|
72
72
|
# This scope selects products in all taxons AND all its descendants
|
@@ -228,7 +228,7 @@ module Spree
|
|
228
228
|
|
229
229
|
# specifically avoid having an order for taxon search (conflicts with main order)
|
230
230
|
def self.prepare_taxon_conditions(taxons)
|
231
|
-
ids = taxons.map { |taxon| taxon.self_and_descendants.
|
231
|
+
ids = taxons.map { |taxon| taxon.self_and_descendants.pluck(:id) }.flatten.uniq
|
232
232
|
joins(:taxons).where("#{Taxon.table_name}.id" => ids)
|
233
233
|
end
|
234
234
|
|
data/app/models/spree/product.rb
CHANGED
@@ -162,7 +162,7 @@ module Spree
|
|
162
162
|
return if option_values_hash.nil?
|
163
163
|
option_values_hash.keys.map(&:to_i).each do |id|
|
164
164
|
self.option_type_ids << id unless option_type_ids.include?(id)
|
165
|
-
product_option_types.create({:option_type_id => id}, :without_protection => true) unless product_option_types.
|
165
|
+
product_option_types.create({:option_type_id => id}, :without_protection => true) unless product_option_types.pluck(:option_type_id).include?(id)
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
@@ -232,10 +232,7 @@ module Spree
|
|
232
232
|
|
233
233
|
def set_property(property_name, property_value)
|
234
234
|
ActiveRecord::Base.transaction do
|
235
|
-
property = Property.where(:name => property_name).
|
236
|
-
property.presentation = property_name
|
237
|
-
property.save!
|
238
|
-
|
235
|
+
property = Property.where(:name => property_name).first_or_create!(:presentation => property_name)
|
239
236
|
product_property = ProductProperty.where(:product_id => id, :property_id => property.id).first_or_initialize
|
240
237
|
product_property.value = property_value
|
241
238
|
product_property.save!
|
@@ -6,7 +6,9 @@ module Spree
|
|
6
6
|
validates :property, :presence => true
|
7
7
|
validates :value, :length => { :maximum => 255 }
|
8
8
|
|
9
|
-
attr_accessible :property_name, :value
|
9
|
+
attr_accessible :property_name, :value, :position
|
10
|
+
|
11
|
+
default_scope :order => "#{self.table_name}.position"
|
10
12
|
|
11
13
|
# virtual attributes for use with AJAX completion stuff
|
12
14
|
def property_name
|