spree_core 1.3.3 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/admin/admin.js.erb +9 -5
  3. data/app/assets/javascripts/store/product.js.coffee +6 -1
  4. data/app/assets/stylesheets/store/screen.css.scss +1 -1
  5. data/app/controllers/spree/admin/images_controller.rb +4 -0
  6. data/app/controllers/spree/admin/resource_controller.rb +6 -2
  7. data/app/controllers/spree/orders_controller.rb +1 -1
  8. data/app/helpers/spree/admin/navigation_helper.rb +3 -1
  9. data/app/models/spree/classification.rb +3 -0
  10. data/app/models/spree/credit_card.rb +13 -0
  11. data/app/models/spree/order.rb +20 -11
  12. data/app/models/spree/payment.rb +1 -1
  13. data/app/models/spree/payment/processing.rb +5 -0
  14. data/app/models/spree/product.rb +1 -1
  15. data/app/models/spree/product/scopes.rb +5 -8
  16. data/app/views/spree/admin/adjustments/index.html.erb +2 -2
  17. data/app/views/spree/admin/payments/_form.html.erb +3 -1
  18. data/app/views/spree/checkout/edit.html.erb +4 -0
  19. data/app/views/spree/orders/_line_item.html.erb +5 -3
  20. data/config/initializers/user_class_extensions.rb +1 -1
  21. data/config/locales/en.yml +6 -0
  22. data/config/routes.rb +1 -1
  23. data/db/migrate/20130626232741_add_cvv_result_code_and_cvv_result_message_to_spree_payments.rb +6 -0
  24. data/db/migrate/20130628021056_add_unique_index_to_permalink_on_spree_products.rb +5 -0
  25. data/db/migrate/20130628022817_add_unique_index_to_orders_shipments_and_stock_transfers.rb +6 -0
  26. data/db/migrate/20130813140619_expand_order_number_size.rb +9 -0
  27. data/lib/generators/spree/dummy/templates/rails/database.yml +0 -3
  28. data/lib/spree/core/permalinks.rb +17 -13
  29. data/lib/spree/core/s3_support.rb +1 -1
  30. data/lib/spree/core/testing_support/factories/variant_factory.rb +1 -1
  31. data/lib/spree/core/version.rb +1 -1
  32. data/vendor/assets/javascripts/jquery.validate/additional-methods.min.js +6 -22
  33. data/vendor/assets/javascripts/jquery.validate/jquery.validate.min.js +6 -45
  34. data/vendor/assets/javascripts/jquery.validate/localization/messages_ar.js +23 -22
  35. data/vendor/assets/javascripts/jquery.validate/localization/messages_bg.js +22 -20
  36. data/vendor/assets/javascripts/jquery.validate/localization/messages_ca.js +22 -20
  37. data/vendor/assets/javascripts/jquery.validate/localization/messages_cs.js +22 -20
  38. data/vendor/assets/javascripts/jquery.validate/localization/messages_da.js +19 -17
  39. data/vendor/assets/javascripts/jquery.validate/localization/messages_de.js +19 -18
  40. data/vendor/assets/javascripts/jquery.validate/localization/messages_el.js +22 -21
  41. data/vendor/assets/javascripts/jquery.validate/localization/messages_es.js +22 -20
  42. data/vendor/assets/javascripts/jquery.validate/localization/messages_et.js +23 -0
  43. data/vendor/assets/javascripts/jquery.validate/localization/messages_eu.js +25 -0
  44. data/vendor/assets/javascripts/jquery.validate/localization/messages_fa.js +22 -20
  45. data/vendor/assets/javascripts/jquery.validate/localization/messages_fi.js +20 -18
  46. data/vendor/assets/javascripts/jquery.validate/localization/messages_fr.js +44 -20
  47. data/vendor/assets/javascripts/jquery.validate/localization/messages_he.js +22 -20
  48. data/vendor/assets/javascripts/jquery.validate/localization/messages_hr.js +25 -0
  49. data/vendor/assets/javascripts/jquery.validate/localization/messages_hu.js +21 -18
  50. data/vendor/assets/javascripts/jquery.validate/localization/messages_it.js +22 -20
  51. data/vendor/assets/javascripts/jquery.validate/localization/messages_ja.js +22 -20
  52. data/vendor/assets/javascripts/jquery.validate/localization/messages_ka.js +25 -0
  53. data/vendor/assets/javascripts/jquery.validate/localization/messages_kk.js +22 -20
  54. data/vendor/assets/javascripts/jquery.validate/localization/messages_ko.js +25 -0
  55. data/vendor/assets/javascripts/jquery.validate/localization/messages_lt.js +23 -21
  56. data/vendor/assets/javascripts/jquery.validate/localization/messages_lv.js +22 -20
  57. data/vendor/assets/javascripts/jquery.validate/localization/messages_my.js +25 -0
  58. data/vendor/assets/javascripts/jquery.validate/localization/messages_nl.js +32 -20
  59. data/vendor/assets/javascripts/jquery.validate/localization/messages_no.js +22 -20
  60. data/vendor/assets/javascripts/jquery.validate/localization/messages_pl.js +22 -20
  61. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_BR.js +26 -0
  62. data/vendor/assets/javascripts/jquery.validate/localization/messages_pt_PT.js +26 -0
  63. data/vendor/assets/javascripts/jquery.validate/localization/messages_ro.js +22 -20
  64. data/vendor/assets/javascripts/jquery.validate/localization/messages_ru.js +22 -20
  65. data/vendor/assets/javascripts/jquery.validate/localization/messages_si.js +21 -19
  66. data/vendor/assets/javascripts/jquery.validate/localization/messages_sk.js +19 -18
  67. data/vendor/assets/javascripts/jquery.validate/localization/messages_sl.js +25 -0
  68. data/vendor/assets/javascripts/jquery.validate/localization/messages_sr.js +23 -21
  69. data/vendor/assets/javascripts/jquery.validate/localization/messages_sv.js +23 -0
  70. data/vendor/assets/javascripts/jquery.validate/localization/messages_th.js +22 -20
  71. data/vendor/assets/javascripts/jquery.validate/localization/messages_tr.js +22 -21
  72. data/vendor/assets/javascripts/jquery.validate/localization/messages_uk.js +25 -0
  73. data/vendor/assets/javascripts/jquery.validate/localization/messages_vi.js +22 -20
  74. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh.js +25 -0
  75. data/vendor/assets/javascripts/jquery.validate/localization/messages_zh_TW.js +26 -0
  76. data/vendor/assets/javascripts/jquery.validate/localization/methods_de.js +6 -6
  77. data/vendor/assets/javascripts/jquery.validate/localization/methods_nl.js +3 -3
  78. data/vendor/assets/javascripts/jquery.validate/localization/methods_pt.js +3 -3
  79. metadata +30 -14
  80. data/app/views/spree/orders/new.html.erb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7dcd25bc09eef1fdc85269018277aa954848fb6f
4
- data.tar.gz: 6c09d32829e4e87e894c38ce1b14b6b307a97f53
3
+ metadata.gz: 8c5bf35a8b95692aa7ff0d8680f50c4c09fca20c
4
+ data.tar.gz: bb49344e459351d49fd48e2f611efb632c91df74
5
5
  SHA512:
6
- metadata.gz: 4c3732fd647f46c1089fb737409226e8abc5bc0c255523f33815a8d1908fdd6f188d4cadb2bb8914db22b3bac65ea60aa8714aec919cbed2a8f475318cd9b536
7
- data.tar.gz: d09f9087d47758599d36bed4852863a7dd8aadbe6dfa11ce5c279cfd654da291a976c535d0f0b159c0325c9279d6fcca7e44db755c1f70b8a195004d125a7873
6
+ metadata.gz: 0cc6f3c95ba0dce27047501a44aa7434479df796de8e30349d929e24bc1566729d915d53cf5e6c7503c157829784b2070f2e37929009d497f75aeb892b3d2ba7
7
+ data.tar.gz: 357cfcbbe86573ef29d1611cd3260957cb5650827724626b5348d2ef38ea356b30746c317ef4f94b59d448dbfb758b2832c60f3ed5a22e4f29d8d1af45360cae
@@ -157,11 +157,11 @@ $(document).ready(function(){
157
157
  var target = $(this).data("target");
158
158
  var new_table_row = $(target + ' tr:visible:last').clone();
159
159
  var new_id = new Date().getTime();
160
- new_table_row.find("input").each(function () {
160
+ new_table_row.find("input, select").each(function () {
161
161
  var el = $(this);
162
162
  el.val("");
163
- el.attr("id", el.attr("id").replace(/\d+/, new_id))
164
- el.attr("name", el.attr("name").replace(/\d+/, new_id))
163
+ if (typeof el.attr("id") !== 'undefined') el.attr("id", el.attr("id").replace(/\d+/, new_id))
164
+ if (typeof el.attr("name") !== 'undefined') el.attr("name", el.attr("name").replace(/\d+/, new_id))
165
165
  })
166
166
  // When cloning a new row, set the href of all icons to be an empty "#"
167
167
  // This is so that clicking on them does not perform the actions for the
@@ -185,7 +185,9 @@ $(document).ready(function(){
185
185
  },
186
186
  dataType: 'script',
187
187
  success: function(response) {
188
- el.parents("tr").fadeOut('hide');
188
+ el.parents("tr").fadeOut('hide', function() {
189
+ $(this).remove();
190
+ })
189
191
  },
190
192
  error: function(response, textStatus, errorThrown) {
191
193
  show_flash_error(response.responseText);
@@ -199,7 +201,9 @@ $(document).ready(function(){
199
201
  el = $(this);
200
202
  el.prev("input[type=hidden]").val("1");
201
203
  el.closest(".fields").hide();
202
- if (el.attr("href")) {
204
+ if (el.attr("href") == '#') {
205
+ el.parents("tr").fadeOut('hide');
206
+ }else if (el.attr("href")) {
203
207
  $.ajax({
204
208
  type: 'POST',
205
209
  url: el.attr("href"),
@@ -35,8 +35,13 @@ update_variant_price = (variant) ->
35
35
  ($ '.price.selling').text(variant_price) if variant_price
36
36
 
37
37
  $ ->
38
+ radios = ($ '#product-variants input[type="radio"]')
38
39
  add_image_handlers()
39
- show_variant_images ($ '#product-variants input[type="radio"]').eq(0).attr('value') if ($ '#product-variants input[type="radio"]').length > 0
40
+
41
+ if radios.length > 0
42
+ show_variant_images radios.eq(0).attr('value')
43
+ update_variant_price radios.first()
44
+
40
45
  ($ '#product-variants input[type="radio"]').click (event) ->
41
46
  show_variant_images @value
42
47
  update_variant_price ($ this)
@@ -300,7 +300,7 @@ mark {background-color: $link_text_color; color: $layout_background_color; font-
300
300
  &#link-to-cart {
301
301
  float: right;
302
302
  padding-left: 24px;
303
- background: url("cart.png") no-repeat left center;
303
+ background: asset-url("cart.png", image) no-repeat left center;
304
304
 
305
305
  &:hover {
306
306
  border-color: $link_text_color;
@@ -9,6 +9,10 @@ module Spree
9
9
 
10
10
  private
11
11
 
12
+ def location_after_destroy
13
+ admin_product_images_url(@product)
14
+ end
15
+
12
16
  def location_after_save
13
17
  admin_product_images_url(@product)
14
18
  end
@@ -70,13 +70,13 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
70
70
  invoke_callbacks(:destroy, :after)
71
71
  flash[:success] = flash_message_for(@object, :successfully_removed)
72
72
  respond_with(@object) do |format|
73
- format.html { redirect_to collection_url }
73
+ format.html { redirect_to location_after_destroy }
74
74
  format.js { render :partial => "spree/admin/shared/destroy" }
75
75
  end
76
76
  else
77
77
  invoke_callbacks(:destroy, :fails)
78
78
  respond_with(@object) do |format|
79
- format.html { redirect_to collection_url }
79
+ format.html { redirect_to location_after_destroy }
80
80
  end
81
81
  end
82
82
  end
@@ -198,6 +198,10 @@ class Spree::Admin::ResourceController < Spree::Admin::BaseController
198
198
  end
199
199
  end
200
200
 
201
+ def location_after_destroy
202
+ collection_url
203
+ end
204
+
201
205
  def location_after_save
202
206
  collection_url
203
207
  end
@@ -26,7 +26,7 @@ module Spree
26
26
  respond_with(@order) do |format|
27
27
  format.html do
28
28
  if params.has_key?(:checkout)
29
- @order.next_transition.run_callbacks
29
+ @order.next_transition.run_callbacks if @order.cart?
30
30
  redirect_to checkout_state_path(@order.checkout_steps.first)
31
31
  else
32
32
  redirect_to cart_path
@@ -143,7 +143,9 @@ module Spree
143
143
  end
144
144
 
145
145
  def configurations_sidebar_menu_item(link_text, url, options = {})
146
- is_active = url.ends_with?(controller.controller_name) || url.ends_with?( "#{controller.controller_name}/edit")
146
+ is_active = url.ends_with?(controller.controller_name) ||
147
+ url.ends_with?("#{controller.controller_name}/edit") ||
148
+ url.ends_with?("#{controller.controller_name.singularize}/edit")
147
149
  options.merge!(:class => is_active ? 'active' : nil)
148
150
  content_tag(:li, options) do
149
151
  link_to(link_text, url)
@@ -3,5 +3,8 @@ module Spree
3
3
  self.table_name = 'spree_products_taxons'
4
4
  belongs_to :product, :class_name => "Spree::Product"
5
5
  belongs_to :taxon, :class_name => "Spree::Taxon"
6
+
7
+ # For #3494
8
+ validates_uniqueness_of :taxon_id, :scope => :product_id, :message => :already_linked
6
9
  end
7
10
  end
@@ -28,6 +28,19 @@ module Spree
28
28
  end
29
29
  end
30
30
 
31
+ # Some payment gateways, such as USA EPay, only support an ActiveMerchant::Billing::CreditCard
32
+ # object, rather than an object *like* that. So we need to convert it.
33
+ def to_active_merchant
34
+ ActiveMerchant::Billing::CreditCard.new(
35
+ :number => number,
36
+ :month => month,
37
+ :year => year,
38
+ :verification_value => verification_value,
39
+ :first_name => first_name,
40
+ :last_name => last_name
41
+ )
42
+ end
43
+
31
44
  # sets self.cc_type while we still have the card number
32
45
  def set_card_type
33
46
  self.cc_type ||= CardDetector.brand?(number)
@@ -17,7 +17,8 @@ module Spree
17
17
  go_to_state :delivery
18
18
  go_to_state :payment, :if => lambda { |order|
19
19
  # Fix for #2191
20
- if order.shipping_method
20
+ # See #3708 also
21
+ if order.total.to_f <= 0 && order.shipping_method
21
22
  order.create_shipment!
22
23
  order.update_totals
23
24
  end
@@ -168,8 +169,13 @@ module Spree
168
169
  end
169
170
 
170
171
  # Used by the checkout state machine to check for unprocessed payments
171
- # The Order should be unable to proceed to complete if there are unprocessed
172
+ # The Order should be only be able to proceed to complete if there are unprocessed
172
173
  # payments and there is payment required.
174
+ #
175
+ # The reason for this is directly before an order transitions to complete, all
176
+ # of the order's payments have `process!` called on it (look in order/checkout.rb).
177
+ # If payment *is* required and there's no payments which haven't already been tried,
178
+ # then the order cannot be paid for and therefore should not be able to become complete.
173
179
  def has_unprocessed_payments?
174
180
  payments.with_state('checkout').reload.exists?
175
181
  end
@@ -340,7 +346,7 @@ module Spree
340
346
  def create_shipment!
341
347
  shipping_method(true)
342
348
  if shipment.present?
343
- shipment.update_attributes!(:shipping_method => shipping_method)
349
+ shipment.update_attributes!({:shipping_method => shipping_method, :inventory_units => self.inventory_units}, :without_protection => true)
344
350
  else
345
351
  self.shipments << Shipment.create!({ :order => self,
346
352
  :shipping_method => shipping_method,
@@ -383,7 +389,7 @@ module Spree
383
389
 
384
390
  # update payment and shipment(s) states, and save
385
391
  updater.update_payment_state
386
- shipments.each { |shipment| shipment.update!(self) }
392
+ shipments.reload.each { |shipment| shipment.update!(self) }
387
393
  updater.update_shipment_state
388
394
  save
389
395
  updater.run_hooks
@@ -491,8 +497,8 @@ module Spree
491
497
  end
492
498
 
493
499
  def empty!
494
- line_items.destroy_all
495
500
  adjustments.destroy_all
501
+ line_items.destroy_all
496
502
  end
497
503
 
498
504
  # destroy any previous adjustments.
@@ -510,12 +516,15 @@ module Spree
510
516
  state = "#{name}_state"
511
517
  if persisted?
512
518
  old_state = self.send("#{state}_was")
513
- self.state_changes.create({
514
- :previous_state => old_state,
515
- :next_state => self.send(state),
516
- :name => name,
517
- :user_id => self.user_id
518
- }, :without_protection => true)
519
+ new_state = self.send(state)
520
+ if old_state != new_state
521
+ self.state_changes.create({
522
+ :previous_state => old_state,
523
+ :next_state => self.send(state),
524
+ :name => name,
525
+ :user_id => self.user_id
526
+ }, :without_protection => true)
527
+ end
519
528
  end
520
529
  end
521
530
 
@@ -8,7 +8,7 @@ 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
11
+ before_create :set_unique_identifier
12
12
 
13
13
  after_save :create_payment_profile, :if => :profiles_supported?
14
14
 
@@ -155,6 +155,11 @@ module Spree
155
155
  unless response.authorization.nil?
156
156
  self.response_code = response.authorization
157
157
  self.avs_response = response.avs_result['code']
158
+
159
+ if response.cvv_result
160
+ self.cvv_response_code = response.cvv_result['code']
161
+ self.cvv_response_message = response.cvv_result['message']
162
+ end
158
163
  end
159
164
  self.send("#{success_state}!")
160
165
  else
@@ -290,7 +290,7 @@ module Spree
290
290
  # there's a weird quirk with the delegate stuff that does not automatically save the delegate object
291
291
  # when saving so we force a save using a hook.
292
292
  def save_master
293
- master.save if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed || master.default_price.new_record)))
293
+ master.save if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
294
294
  end
295
295
 
296
296
  def ensure_master
@@ -68,14 +68,11 @@ module Spree
68
68
  #
69
69
  # SELECT COUNT(*) ...
70
70
  add_search_scope :in_taxon do |taxon|
71
- if ActiveRecord::Base.connection.adapter_name == "PostgreSQL"
72
- scope = select("DISTINCT ON (spree_products.id) spree_products.*")
73
- else
74
- scope = select("DISTINCT(spree_products.id), spree_products.*")
75
- end
76
-
77
- scope.joins(:taxons).
78
- where(Taxon.table_name => { :id => taxon.self_and_descendants.map(&:id) })
71
+ select("spree_products.id, spree_products.*").
72
+ where(id: Classification.select('spree_products_taxons.product_id').
73
+ joins(:taxon).
74
+ where(Taxon.table_name => { :id => taxon.self_and_descendants.pluck(:id) })
75
+ )
79
76
  end
80
77
 
81
78
  # This scope selects products in all taxons AND all its descendants
@@ -4,11 +4,11 @@
4
4
  <i class="icon-arrow-right"></i> <%= t(:adjustments) %>
5
5
  <% end %>
6
6
 
7
- <% content_for :page_actions do %>
7
+ <% content_for :page_actions do %>
8
8
  <li><%= button_link_to t(:new_adjustment), new_admin_order_adjustment_url(@order), :icon => 'icon-plus' %></li>
9
9
  <li><%= button_link_to t(:back_to_orders_list), admin_orders_path, :icon => 'icon-arrow-left' %></li>
10
10
  <% end %>
11
11
 
12
12
  <%= render :partial => 'adjustments_table' %>
13
13
 
14
- <%= button_link_to t(:continue), @order.cart? ? new_admin_order_payment_url(@order) : admin_orders_url, :icon => 'icon-arrow-right' %>
14
+ <%= button_link_to t(:continue), @order.payment? ? new_admin_order_payment_url(@order) : admin_orders_url, :icon => 'icon-arrow-right' %>
@@ -20,7 +20,9 @@
20
20
  </ul>
21
21
  <div class="payment-method-settings">
22
22
  <% @payment_methods.each do |method| %>
23
- <%= render :partial => "spree/admin/payments/source_forms/#{method.method_type}", :locals => { :payment_method => method } %>
23
+ <% if method.source_required? %>
24
+ <%= render :partial => "spree/admin/payments/source_forms/#{method.method_type}", :locals => { :payment_method => method } %>
25
+ <% end %>
24
26
  <% end %>
25
27
  </div>
26
28
  </div>
@@ -31,3 +31,7 @@
31
31
  </div>
32
32
 
33
33
  </div>
34
+
35
+ <% if I18n.locale != :en %>
36
+ <script src='/assets/jquery.validate/localization/messages_<%= I18n.locale %>.js'></script>
37
+ <% end %>
@@ -11,10 +11,12 @@
11
11
  <%= variant.options_text %>
12
12
  <% if @order.insufficient_stock_lines.include? line_item %>
13
13
  <span class="out-of-stock">
14
- <%= variant.in_stock? ? t(:insufficient_stock, :on_hand => variant.on_hand) : t(:out_of_stock) %>&nbsp;&nbsp;<br />
15
- </span>
14
+ <%= variant.in_stock? ? t(:insufficient_stock, :on_hand => variant.on_hand) : t(:out_of_stock) %>
15
+ </span><br />
16
16
  <% end %>
17
- <%= line_item_description(variant) %>
17
+ <span class="line-item-description" data-hook="line_item_description">
18
+ <%= line_item_description(variant) %>
19
+ </span>
18
20
  </td>
19
21
  <td class="cart-item-price" data-hook="cart_item_price">
20
22
  <%= line_item.single_money.to_html %>
@@ -18,7 +18,7 @@ Spree::Core::Engine.config.to_prepare do
18
18
  end
19
19
 
20
20
  def last_incomplete_spree_order
21
- spree_orders.incomplete.order('created_at DESC').last
21
+ spree_orders.incomplete.order('created_at DESC').first
22
22
  end
23
23
  end
24
24
  end
@@ -209,6 +209,12 @@ en:
209
209
  spree/zone:
210
210
  one: Zone
211
211
  other: Zones
212
+ errors:
213
+ models:
214
+ spree/classification:
215
+ attributes:
216
+ taxon_id:
217
+ already_linked: "is already linked to this product"
212
218
  add: Add
213
219
  add_category: "Add Category"
214
220
  add_country: "Add Country"
@@ -22,7 +22,7 @@ Spree::Core::Engine.routes.draw do
22
22
  get '/orders/populate', :via => :get, :to => populate_redirect
23
23
  match '/orders/:id/token/:token' => 'orders#show', :via => :get, :as => :token_order
24
24
 
25
- resources :orders do
25
+ resources :orders, :except => [:new, :create] do
26
26
  post :populate, :on => :collection
27
27
  end
28
28
 
@@ -0,0 +1,6 @@
1
+ class AddCvvResultCodeAndCvvResultMessageToSpreePayments < ActiveRecord::Migration
2
+ def change
3
+ add_column :spree_payments, :cvv_response_code, :string
4
+ add_column :spree_payments, :cvv_response_message, :string
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class AddUniqueIndexToPermalinkOnSpreeProducts < ActiveRecord::Migration
2
+ def change
3
+ add_index "spree_products", ["permalink"], :name => "permalink_idx_unique", :unique => true
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class AddUniqueIndexToOrdersShipmentsAndStockTransfers < ActiveRecord::Migration
2
+ def add
3
+ add_index "spree_orders", ["number"], :name => "number_idx_unique", :unique => true
4
+ add_index "spree_shipments", ["number"], :name => "number_idx_unique", :unique => true
5
+ end
6
+ end
@@ -0,0 +1,9 @@
1
+ class ExpandOrderNumberSize < ActiveRecord::Migration
2
+ def up
3
+ change_column :spree_orders, :number, :string, :limit => 32
4
+ end
5
+
6
+ def down
7
+ change_column :spree_orders, :number, :string, :limit => 15
8
+ end
9
+ end
@@ -16,17 +16,14 @@ production:
16
16
  development:
17
17
  adapter: mysql2
18
18
  database: <%= database_prefix %>spree_development
19
- username:
20
19
  encoding: utf8
21
20
  test:
22
21
  adapter: mysql2
23
22
  database: <%= database_prefix %>spree_test
24
- username:
25
23
  encoding: utf8
26
24
  production:
27
25
  adapter: mysql2
28
26
  database: <%= database_prefix %>spree_production
29
- username:
30
27
  encoding: utf8
31
28
  <% when 'postgres' %>
32
29
  development:
@@ -14,9 +14,9 @@ module Spree
14
14
  options[:field] ||= :permalink
15
15
  self.permalink_options = options
16
16
 
17
- validates permalink_options[:field], :uniqueness => true
18
-
19
- before_validation(:on => :create) { save_permalink }
17
+ if self.table_exists? && self.column_names.include?(permalink_options[:field].to_s)
18
+ before_validation(:on => :create) { save_permalink }
19
+ end
20
20
  end
21
21
 
22
22
  def find_by_param(value, *args)
@@ -38,16 +38,20 @@ module Spree
38
38
  end
39
39
 
40
40
  def save_permalink(permalink_value=self.to_param)
41
- field = self.class.permalink_field
42
- # Do other links exist with this permalink?
43
- other = self.class.where("#{self.class.table_name}.#{field} LIKE ?", "#{permalink_value}%")
44
- if other.any?
45
- # Find the existing permalink with the highest number, and increment that number.
46
- # (If none of the existing permalinks have a number, this will evaluate to 1.)
47
- number = other.map { |o| o.send(field)[/-(\d+)$/, 1].to_i }.max + 1
48
- permalink_value += "-#{number.to_s}"
49
- end
50
- write_attribute(field, permalink_value)
41
+ self.with_lock do
42
+ permalink_value ||= generate_permalink
43
+
44
+ field = self.class.permalink_field
45
+ # Do other links exist with this permalink?
46
+ other = self.class.select(field).where("#{self.class.table_name}.#{field} LIKE ?", "#{permalink_value}%")
47
+ if other.any?
48
+ # Find the existing permalink with the highest number, and increment that number.
49
+ # (If none of the existing permalinks have a number, this will evaluate to 1.)
50
+ number = other.map { |o| o.send(field)[/-(\d+)$/, 1].to_i }.max + 1
51
+ permalink_value += "-#{number.to_s}"
52
+ end
53
+ write_attribute(field, permalink_value)
54
+ end
51
55
  end
52
56
  end
53
57
  end