spree_core 1.0.0.rc3 → 1.0.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/app/assets/images/admin/payment_banner.png +0 -0
  2. data/app/assets/javascripts/admin/admin.js.erb +16 -5
  3. data/app/assets/javascripts/admin/spree_core.js +0 -1
  4. data/app/assets/javascripts/store/spree_core.js +0 -1
  5. data/app/assets/stylesheets/admin/admin.css.erb +57 -3
  6. data/app/assets/stylesheets/store/screen.css.scss +72 -29
  7. data/app/assets/stylesheets/store/spree_core.css +5 -4
  8. data/app/controllers/spree/admin/tax_categories_controller.rb +13 -0
  9. data/app/controllers/spree/admin/users_controller.rb +16 -0
  10. data/app/controllers/spree/products_controller.rb +1 -1
  11. data/app/helpers/spree/admin/navigation_helper.rb +3 -1
  12. data/app/models/spree/payment_method.rb +2 -0
  13. data/app/models/spree/preferences/preferable.rb +32 -1
  14. data/app/models/spree/preferences/preferable_class_methods.rb +21 -4
  15. data/app/models/spree/product.rb +4 -3
  16. data/app/models/spree/tax_category.rb +7 -1
  17. data/app/models/spree/tax_rate.rb +4 -1
  18. data/app/models/spree/user.rb +2 -0
  19. data/app/views/spree/admin/banners/_gateway.html.erb +14 -0
  20. data/app/views/spree/admin/images/index.html.erb +4 -4
  21. data/app/views/spree/admin/option_types/index.html.erb +2 -2
  22. data/app/views/spree/admin/payment_methods/index.html.erb +2 -0
  23. data/app/views/spree/admin/variants/index.html.erb +2 -2
  24. data/app/views/spree/orders/_line_item.html.erb +4 -4
  25. data/app/views/spree/shared/_order_details.html.erb +8 -9
  26. data/config/locales/en.yml +4 -0
  27. data/config/routes.rb +6 -3
  28. data/db/migrate/20120203153759_add_deleted_at_to_tax_category.rb +5 -0
  29. data/lib/spree/core/middleware/seo_assist.rb +1 -1
  30. data/lib/spree/core/user_banners.rb +25 -0
  31. data/lib/spree/core/version.rb +1 -1
  32. data/vendor/assets/images/jquery.formalize/button.png +0 -0
  33. data/vendor/assets/images/jquery.formalize/select_arrow.gif +0 -0
  34. data/vendor/assets/stylesheets/html5reset.css +177 -0
  35. data/vendor/assets/stylesheets/{jquery.formalize.css → jquery.formalize.css.erb} +3 -3
  36. data/{app/assets/stylesheets/store/base.css → vendor/assets/stylesheets/skeleton.css} +14 -159
  37. metadata +37 -31
  38. data/app/assets/javascripts/store/helpers.js.erb +0 -2
@@ -1,4 +1,3 @@
1
- //= require store/helpers
2
1
  //= require_self
3
2
 
4
3
  /**
@@ -17,6 +16,20 @@ $(document).ajaxStop(function(){
17
16
 
18
17
  $.fn.visible = function(cond) { this[cond ? 'show' : 'hide' ]() };
19
18
 
19
+ show_flash_error = function(message) {
20
+ error_div = $('.flash.error');
21
+ if (error_div.length > 0) {
22
+ error_div.html(message);
23
+ error_div.show();
24
+ } else {
25
+ if ($("#content .toolbar").length > 0) {
26
+ $("#content .toolbar").before('<div class="flash error">' + message + '</div>');
27
+ } else {
28
+ $("#content h1").before('<div class="flash error">' + message + '</div>');
29
+ }
30
+ }
31
+ }
32
+
20
33
  // Apply to individual radio button that makes another element visible when checked
21
34
  $.fn.radioControlsVisibilityOfElement = function(dependentElementSelector){
22
35
  if(!this.get(0)){ return }
@@ -227,19 +240,17 @@ $(document).ready(function(){
227
240
  update: function(event, ui) {
228
241
  $("#progress").show();
229
242
  positions = {};
230
- type = '';
231
243
  $.each($('table.sortable tbody tr'), function(position, obj){
232
244
  reg = /spree_(\w+_?)+_(\d+)/;
233
245
  parts = reg.exec($(obj).attr('id'));
234
246
  if (parts) {
235
247
  positions['positions['+parts[2]+']'] = position;
236
- type = parts[1];
237
248
  }
238
249
  });
239
250
  $.ajax({
240
251
  type: 'POST',
241
252
  dataType: 'script',
242
- url: Spree.base_path + 'admin/' + type + 's/update_positions',
253
+ url: $(ui.item).closest("table.sortable").data("sortable-link"),
243
254
  data: positions,
244
255
  success: function(data){ $("#progress").hide(); }
245
256
  });
@@ -250,7 +261,7 @@ $(document).ready(function(){
250
261
  });
251
262
 
252
263
  jQuery(document).ready(function() {
253
- $('div.alert a.dismiss').click(function() {
264
+ $('a.dismiss').click(function() {
254
265
  $(this).parent().fadeOut();
255
266
  });
256
267
  });
@@ -6,5 +6,4 @@
6
6
  //= require jquery.delayedobserver
7
7
  //= require jquery.jstree/jquery.jstree
8
8
  //= require jquery.alerts/jquery.alerts
9
- //= require store/helpers
10
9
  //= require_tree .
@@ -5,4 +5,3 @@
5
5
  //= require store/checkout
6
6
  //= require store/product
7
7
  //= require store/cart
8
- //= require store/helpers
@@ -616,17 +616,71 @@ span.handle{
616
616
  font-size: 0.8em;
617
617
  }
618
618
  .alert.release {
619
- background: #ccddff url(../images/shadow_top.png) 0px -50px repeat-x;
619
+ background-color: #ccddff;
620
620
  color: #556699;
621
621
  border: 1px solid #99aacc;
622
622
  }
623
623
  .alert.security {
624
- background: #f4b4b4 url(../images/shadow_top.png) 0px -50px repeat-x;
624
+ background-color: #f4b4b4;
625
625
  color: #000000;
626
626
  border: 1px solid #e75b5b;
627
627
  }
628
628
  .alert.news {
629
- background: #ccffd4 url(../images/shadow_top.png) 0px -50px repeat-x;
629
+ background-color: #ccffd4;
630
630
  color: #000000;
631
631
  border: 1px solid #66ff7e;
632
632
  }
633
+
634
+ /* Spree analytics preview buttons */
635
+ .analytics_splash{
636
+ text-align: center;
637
+ }
638
+ .preview-buttons {
639
+ position: absolute;
640
+ left: 860px;
641
+ top: 820px;
642
+ }
643
+ .preview-buttons a.button {
644
+ display: inline-block;
645
+ float: none;
646
+ font-size: 14px;
647
+ }
648
+
649
+ /* Spree admin banners*/
650
+ .banner {
651
+ overflow: auto;
652
+ }
653
+ .banner p {
654
+ text-transform: uppercase;
655
+ font-weight: bold;
656
+ }
657
+ .banner .button {
658
+ float: none !important;
659
+ display: inline-block;
660
+ }
661
+
662
+ .banner.payment_banner {
663
+ width: 739px;
664
+ height: 135px;
665
+ background: transparent url(<%= asset_path 'admin/payment_banner.png' %>) no-repeat left top;
666
+ position: absolute;
667
+ left: -17px;
668
+ }
669
+ .banner.payment_banner .message {
670
+ padding-left: 40px;
671
+ padding-top: 35px;
672
+ font-size: 16px;
673
+ width: 500px;
674
+ color: #5A81B3;
675
+ line-height: 25px;
676
+ }
677
+ .banner.payment_banner .message a {
678
+ color: #82a653 !important;
679
+ }
680
+
681
+ .banner.payment_banner .dismiss {
682
+ color: #B25B59 !important;
683
+ font-weight: bold;
684
+ float: right;
685
+ margin-right: 25px;
686
+ }
@@ -2,13 +2,18 @@
2
2
  /* Colors
3
3
  /*--------------------------------------*/
4
4
  $c_base: #404042; /* Dark gray */
5
- $c_gray1: #bbbbbb; /* Mid light gray */
5
+ $c_gray: #bbbbbb; /* Mid light gray */
6
6
  $c_colored: #00ADEE; /* Light blue */
7
7
  $c_colored_alt: #f0f8ff; /* Lighter blue */
8
8
  $c_border: #dedede; /* Light gray */
9
9
  $c_green: #8dba53; /* Spree green */
10
10
  $c_red: #e45353; /* Error red */
11
11
 
12
+ /*--------------------------------------*/
13
+ /* Fonts
14
+ /*--------------------------------------*/
15
+ @import url(http://fonts.googleapis.com/css?family=Ubuntu:400,700,400italic,700italic|&subset=latin,cyrillic,greek,greek-ext,latin-ext,cyrillic-ext);
16
+
12
17
  /*--------------------------------------*/
13
18
  /* Basic styles
14
19
  /*--------------------------------------*/
@@ -19,6 +24,11 @@ body {
19
24
  font-size: 12px;
20
25
  }
21
26
 
27
+ /* Line style */
28
+ hr {
29
+ border-color: $c_border;
30
+ }
31
+
22
32
  /* Custom text-selection colors (remove any text shadows: twitter.com/miketaylr/status/12228805301) */
23
33
  ::-moz-selection{background: $c_colored; color: white; text-shadow: none;}
24
34
  ::selection {background: $c_colored; color: white; text-shadow: none;}
@@ -55,27 +65,25 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
55
65
  }
56
66
  }
57
67
  }
58
-
59
68
 
60
- dl {
61
- dt, dd {
62
- display: inline-block;
63
- width: 50%;
64
- padding: 5px;
69
+ dl {
70
+ dt, dd {
71
+ display: inline-block;
72
+ width: 50%;
73
+ padding: 5px;
65
74
 
66
- &.odd {
67
- background-color: $c_border;
68
- }
69
- }
70
- dt {
71
- font-weight: bold;
72
- text-transform: uppercase;
73
- }
74
- dd {
75
- margin-left: -23px;
75
+ &.odd {
76
+ background-color: $c_border;
76
77
  }
77
78
  }
78
-
79
+ dt {
80
+ font-weight: bold;
81
+ text-transform: uppercase;
82
+ }
83
+ dd {
84
+ margin-left: -23px;
85
+ }
86
+ }
79
87
 
80
88
  /*--------------------------------------*/
81
89
  /* Headers
@@ -90,7 +98,6 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
90
98
  h5 { font-size: 16px; line-height: 26px; }
91
99
  h6 { font-size: 14px; line-height: 24px; }
92
100
 
93
-
94
101
  /*--------------------------------------*/
95
102
  /* Forms
96
103
  /*--------------------------------------*/
@@ -121,6 +128,13 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
121
128
  select {
122
129
  border: 1px solid $c_border;
123
130
  font-family: "Ubuntu", sans-serif;
131
+ background-image: url('select_arrow.gif');
132
+ background-repeat: no-repeat;
133
+ background-position: right center;
134
+
135
+ &:active, &:focus {
136
+ @extend input[type="text"]:focus
137
+ }
124
138
  }
125
139
 
126
140
  label.error {
@@ -142,7 +156,6 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
142
156
  -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
143
157
  -khtml-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
144
158
  -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
145
- -ms-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
146
159
  -o-box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
147
160
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.4);
148
161
  -webkit-border-radius: 0px;
@@ -290,7 +303,7 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
290
303
  font-weight: bold;
291
304
  border-left: 1px solid $c_border;
292
305
  padding-left: 5px;
293
- padding-bottom: 8px;
306
+ padding-bottom: 5px;
294
307
  }
295
308
  }
296
309
  }
@@ -386,7 +399,10 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
386
399
  margin-top: 15px;
387
400
 
388
401
  input[type="number"] {
389
- width: 40px;
402
+ width: 60px;
403
+ vertical-align: middle;
404
+ padding: 5px;
405
+ height: 35px;
390
406
  }
391
407
  }
392
408
 
@@ -417,7 +433,7 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
417
433
  &.info {
418
434
  height: 35px;
419
435
  margin-top: 5px;
420
- color: $c_gray1;
436
+ color: $c_gray;
421
437
  border-bottom: 1px solid $c_border;
422
438
  }
423
439
  }
@@ -534,7 +550,7 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
534
550
  font-weight: bold;
535
551
  text-transform: uppercase;
536
552
  padding: 5px 20px;
537
- color: $c_gray1;
553
+ color: $c_gray;
538
554
 
539
555
  &.current-first, &.current {
540
556
  background-color: $c_colored;
@@ -638,7 +654,7 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
638
654
 
639
655
  table tfoot {
640
656
  text-align: right;
641
- color: $c_gray1;
657
+ color: $c_gray;
642
658
 
643
659
  tr {
644
660
  border: none;
@@ -723,7 +739,7 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
723
739
  #subtotal {
724
740
  text-align: right;
725
741
  text-transform: uppercase;
726
- margin-top: 10px;
742
+ margin-top: 15px;
727
743
 
728
744
  span.order-total {
729
745
  @extend span.price;
@@ -878,6 +894,33 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
878
894
  }
879
895
  }
880
896
 
897
+ table#cart-detail, table[data-hook="order_details"] {
898
+ tbody {
899
+ tr {
900
+ td[data-hook="cart_item_description"], td[data-hook="order_item_description"] {
901
+ font-size: 11px;
902
+ line-height: 15px;
903
+ width: 100px;
904
+
905
+ h4 {
906
+ font-size: 14px;
907
+ line-height: 17px;
908
+ margin-bottom: 10px;
909
+ }
910
+ }
911
+ td[data-hook="cart_item_price"], td[data-hook="cart_item_total"],
912
+ td[data-hook="order_item_price"], td[data-hook="order_item_total"] {
913
+ font-size: 12px !important;
914
+ }
915
+ td[data-hook="cart_item_image"], td[data-hook="order_item_image"] {
916
+ img {
917
+ width: 70px;
918
+ }
919
+ }
920
+ }
921
+ }
922
+ }
923
+
881
924
  }
882
925
 
883
926
 
@@ -907,10 +950,10 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
907
950
  margin-top: 0;
908
951
  }
909
952
 
910
- table#cart-detail {
953
+ table#cart-detail, table[data-hook="order_details"] {
911
954
  tbody {
912
955
  tr {
913
- td[data-hook="cart_item_description"] {
956
+ td[data-hook="cart_item_description"], td[data-hook="order_item_description"] {
914
957
  padding: 0 !important;
915
958
  text-indent: -9999px;
916
959
 
@@ -918,7 +961,7 @@ mark {background-color: $c_colored; color: white; font-style: italic; font-weigh
918
961
  display: none;
919
962
  }
920
963
  }
921
- td[data-hook="cart_item_image"] {
964
+ td[data-hook="cart_item_image"], td[data-hook="order_item_image"] {
922
965
  img {
923
966
  width: 70px;
924
967
  }
@@ -1,6 +1,7 @@
1
1
  /*
2
- * This is a manifest file that includes stylesheets for spree_core
3
- *= require store/base
4
- *= require jquery.formalize.css
2
+ * This is a manifest file that includes stylesheets for spree_core
3
+ *= require html5reset
4
+ *= require skeleton
5
+ *= require jquery.formalize
5
6
  *= require store/screen
6
- */
7
+ */
@@ -1,6 +1,19 @@
1
1
  module Spree
2
2
  module Admin
3
3
  class TaxCategoriesController < ResourceController
4
+ def destroy
5
+ if @object.mark_deleted!
6
+ flash.notice = flash_message_for(@object, :successfully_removed)
7
+ respond_with(@object) do |format|
8
+ format.html { redirect_to collection_url }
9
+ format.js { render :partial => "spree/admin/shared/destroy" }
10
+ end
11
+ else
12
+ respond_with(@object) do |format|
13
+ format.html { redirect_to collection_url }
14
+ end
15
+ end
16
+ end
4
17
  end
5
18
  end
6
19
  end
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  module Admin
3
3
  class UsersController < ResourceController
4
+ rescue_from User::DestroyWithOrdersError, :with => :user_destroy_with_orders_error
5
+
4
6
  # http://spreecommerce.com/blog/2010/11/02/json-hijacking-vulnerability/
5
7
  before_filter :check_json_authenticity, :only => :index
6
8
  before_filter :load_roles, :only => [:edit, :new, :update, :create]
@@ -16,6 +18,13 @@ module Spree
16
18
  end
17
19
  end
18
20
 
21
+ def dismiss_banner
22
+ if request.xhr? and params[:banner_id]
23
+ current_user.dismiss_banner(params[:banner_id])
24
+ render :nothing => true
25
+ end
26
+ end
27
+
19
28
  protected
20
29
  def collection
21
30
  return @collection if @collection.present?
@@ -48,6 +57,13 @@ module Spree
48
57
  end
49
58
 
50
59
  private
60
+
61
+ # handling raise from Admin::ResourceController#destroy
62
+ def user_destroy_with_orders_error
63
+ invoke_callbacks(:destroy, :fails)
64
+ render :status => :forbidden, :text => t(:error_user_destroy_with_orders)
65
+ end
66
+
51
67
  # Allow different formats of json data to suit different ajax calls
52
68
  def json_data
53
69
  json_format = params[:json_format] or 'default'
@@ -7,7 +7,7 @@ module Spree
7
7
  respond_to :html
8
8
 
9
9
  def index
10
- @searcher = Spree::Config.searcher_class.new(params)
10
+ @searcher = Config.searcher_class.new(params)
11
11
  @products = @searcher.retrieve_products
12
12
  respond_with(@products)
13
13
  end
@@ -64,6 +64,7 @@ module Spree
64
64
  options.reverse_merge! :title => t(:confirm_delete)
65
65
  options.reverse_merge! :dataType => 'script'
66
66
  options.reverse_merge! :success => "function(r){ $('##{dom_id resource}').fadeOut('hide'); }"
67
+ options.reverse_merge! :error => "function(jqXHR, textStatus, errorThrown){ show_flash_error(jqXHR.responseText); }"
67
68
  options.reverse_merge! :name => icon('delete') + ' ' + t(:delete)
68
69
 
69
70
  link_to_function_delete(options, html_options)
@@ -92,7 +93,8 @@ module Spree
92
93
  url: '#{options[:url]}',
93
94
  data: ({_method: 'delete', authenticity_token: AUTH_TOKEN}),
94
95
  dataType:'#{options[:dataType]}',
95
- success: #{options[:success]}
96
+ success: #{options[:success]},
97
+ error: #{options[:error]}
96
98
  });
97
99
  }
98
100
  end
@@ -3,6 +3,8 @@ module Spree
3
3
  DISPLAY = [:both, :front_end, :back_end]
4
4
  default_scope where(:deleted_at => nil)
5
5
 
6
+ scope :production, where(:environment => 'production')
7
+
6
8
  def self.providers
7
9
  Rails.application.config.spree.payment_methods
8
10
  end
@@ -1,3 +1,8 @@
1
+ # The preference_cache_key is used to determine if the preference
2
+ # can be set. The default behavior is to return nil if there is no
3
+ # id value. On ActiveRecords, new objects will have their preferences
4
+ # saved to a pending hash until it is persisted.
5
+ #
1
6
  # class_attributes are inheritied unless you reassign them in
2
7
  # the subclass, so when you inherit a Preferable class, the
3
8
  # inherited hook will assign a new hash for the subclass definitions
@@ -8,11 +13,19 @@ module Spree::Preferences::Preferable
8
13
  def self.included(base)
9
14
  base.class_eval do
10
15
  extend Spree::Preferences::PreferableClassMethods
16
+
17
+ if respond_to?(:after_create)
18
+ after_create do |obj|
19
+ obj.save_pending_preferences
20
+ end
21
+ end
22
+
11
23
  if respond_to?(:after_destroy)
12
24
  after_destroy do |obj|
13
25
  obj.clear_preferences
14
26
  end
15
27
  end
28
+
16
29
  end
17
30
  end
18
31
 
@@ -64,7 +77,15 @@ module Spree::Preferences::Preferable
64
77
  end
65
78
 
66
79
  def preference_cache_key(name)
67
- [self.class.name, name, (try(:id) || :new)].join('::').underscore
80
+ return unless id
81
+ [self.class.name, name, id].join('::').underscore
82
+ end
83
+
84
+ def save_pending_preferences
85
+ return unless @pending_preferences
86
+ @pending_preferences.each do |name, value|
87
+ set_preference(name, value)
88
+ end
68
89
  end
69
90
 
70
91
  def clear_preferences
@@ -73,6 +94,16 @@ module Spree::Preferences::Preferable
73
94
 
74
95
  private
75
96
 
97
+ def add_pending_preference(name, value)
98
+ @pending_preferences ||= {}
99
+ @pending_preferences[name] = value
100
+ end
101
+
102
+ def get_pending_preference(name)
103
+ return unless @pending_preferences
104
+ @pending_preferences[name]
105
+ end
106
+
76
107
  def preference_store
77
108
  Spree::Preferences::Store.instance
78
109
  end
@@ -7,11 +7,17 @@ module Spree::Preferences
7
7
  default = options[:default]
8
8
  description = options[:description] || name
9
9
 
10
+ # cache_key will be nil for new objects, then if we check if there
11
+ # is a pending preference before going to default
10
12
  define_method preference_getter_method(name) do
11
- if preference_store.exist? preference_cache_key(name)
13
+ if preference_cache_key(name) && preference_store.exist?(preference_cache_key(name))
12
14
  preference_store.get preference_cache_key(name)
13
15
  else
14
- send self.class.preference_default_getter_method(name)
16
+ if get_pending_preference(name)
17
+ get_pending_preference(name)
18
+ else
19
+ send self.class.preference_default_getter_method(name)
20
+ end
15
21
  end
16
22
  end
17
23
  alias_method prefers_getter_method(name), preference_getter_method(name)
@@ -20,9 +26,20 @@ module Spree::Preferences
20
26
  # Boolean attributes can come back from forms as '0' or '1'
21
27
  # Convert them to their correct values here
22
28
  if type == :boolean && !value.is_a?(TrueClass) && !value.is_a?(FalseClass)
23
- value = value.to_i == 1
29
+ value = value.downcase if value.respond_to? :downcase
30
+ case value
31
+ when 0, '0', 'false', 'f', "", []
32
+ value = false
33
+ else
34
+ value = true
35
+ end
36
+ end
37
+
38
+ if preference_cache_key(name)
39
+ preference_store.set preference_cache_key(name), value
40
+ else
41
+ add_pending_preference(name, value)
24
42
  end
25
- preference_store.set preference_cache_key(name), value
26
43
  end
27
44
  alias_method prefers_setter_method(name), preference_setter_method(name)
28
45
 
@@ -140,10 +140,11 @@ module Spree
140
140
  image_dup = lambda { |i| j = i.dup; j.attachment = i.attachment.clone; j }
141
141
  p.images = self.images.map { |i| image_dup.call i }
142
142
 
143
- variant = self.master.dup
144
- variant.sku = 'COPY OF ' + self.master.sku
143
+ master = Spree::Variant.find_by_product_id_and_is_master(self.id, true)
144
+ variant = master.dup
145
+ variant.sku = 'COPY OF ' + master.sku
145
146
  variant.deleted_at = nil
146
- variant.images = self.master.images.map { |i| image_dup.call i }
147
+ variant.images = master.images.map { |i| image_dup.call i }
147
148
  p.master = variant
148
149
 
149
150
  if self.has_variants?
@@ -1,11 +1,13 @@
1
1
  module Spree
2
2
  class TaxCategory < ActiveRecord::Base
3
- validates :name, :presence => true, :uniqueness => true
3
+ validates :name, :presence => true, :uniqueness => { :scope => :deleted_at }
4
4
 
5
5
  has_many :tax_rates, :dependent => :destroy
6
6
 
7
7
  before_save :set_default_category
8
8
 
9
+ default_scope where(:deleted_at => nil)
10
+
9
11
  def set_default_category
10
12
  #set existing default tax category to false if this one has been marked as default
11
13
 
@@ -14,5 +16,9 @@ module Spree
14
16
  end
15
17
  end
16
18
 
19
+ def mark_deleted!
20
+ self.deleted_at = Time.now
21
+ self.save
22
+ end
17
23
  end
18
24
  end
@@ -35,7 +35,10 @@ module Spree
35
35
  category = TaxCategory.includes(:tax_rates).where(:is_default => true).first
36
36
  return 0 unless category
37
37
 
38
- category.effective_amount || 0
38
+ address ||= Address.new(:country_id => Spree::Config[:default_country_id])
39
+ rate = category.tax_rates.detect { |rate| rate.zone.include? address }.try(:amount)
40
+
41
+ rate || 0
39
42
  end
40
43
 
41
44
  # Creates necessary tax adjustments for the order.
@@ -1,6 +1,8 @@
1
1
  # Default implementation of User. This class is intended to be modified by extensions (ex. spree_auth)
2
2
  module Spree
3
3
  class User < ActiveRecord::Base
4
+ include Core::UserBanners
5
+
4
6
  has_many :orders
5
7
 
6
8
  belongs_to :ship_address, :foreign_key => 'ship_address_id', :class_name => 'Spree::Address'
@@ -0,0 +1,14 @@
1
+ <% if !current_user.dismissed_banner?(:gateway) &&
2
+ Spree::PaymentMethod.production.where("type != 'Spree::Gateway::Bogus'").empty? %>
3
+
4
+ <div class="banner payment_banner">
5
+ <p class="message">
6
+ <%= t(:payment_processor_choose_banner_text)%>
7
+ <%= link_to t(:payment_processor_choose_link), "http://spreecommerce.com/products/gateway", :target => '_blank' %>
8
+ </p>
9
+
10
+ <%= link_to t(:dismiss_banner), dismiss_banner_admin_user_path(current_user, :banner_id => :gateway),
11
+ :remote => true, :method => :post, :class => 'dismiss' %>
12
+ </div>
13
+
14
+ <% end %>