diff --git a/app/assets/javascripts/darkswarm/services/cart.js.coffee b/app/assets/javascripts/darkswarm/services/cart.js.coffee index 973170e414..4f808e0710 100644 --- a/app/assets/javascripts/darkswarm/services/cart.js.coffee +++ b/app/assets/javascripts/darkswarm/services/cart.js.coffee @@ -1,4 +1,4 @@ -Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)-> +Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, storage)-> # Handles syncing of current cart/order state to server new class Cart dirty: false @@ -41,21 +41,30 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, storage)-> @update_running = false compareAndNotifyStockLevels: (stockLevels) => + scope = $rootScope.$new(true) + scope.variants = [] + + # TODO: These changes to quantity/max_quantity trigger another cart update, which + # is unnecessary. + for li in @line_items_present() if !stockLevels[li.variant.id]? - alert "Variant out of stock: #{li.variant.id}" li.quantity = 0 li.max_quantity = 0 if li.max_quantity? li.variant.count_on_hand = 0 + scope.variants.push li.variant else if stockLevels[li.variant.id].quantity < li.quantity - alert "Variant quantity reduced: #{li.variant.id}" li.quantity = stockLevels[li.variant.id].quantity + scope.variants.push li.variant if stockLevels[li.variant.id].max_quantity < li.max_quantity - alert "Variant max_quantity reduced: #{li.variant.id}" li.max_quantity = stockLevels[li.variant.id].max_quantity + scope.variants.push li.variant li.variant.count_on_hand = stockLevels[li.variant.id].on_hand + if scope.variants.length > 0 + $modal.open(templateUrl: "out_of_stock.html", scope: scope, windowClass: 'out-of-stock-modal') + popQueue: => @update_enqueued = false @scheduleUpdate() diff --git a/app/assets/javascripts/templates/out_of_stock.html.haml b/app/assets/javascripts/templates/out_of_stock.html.haml new file mode 100644 index 0000000000..72244d7ab6 --- /dev/null +++ b/app/assets/javascripts/templates/out_of_stock.html.haml @@ -0,0 +1,10 @@ +%h3 Reduced stock available + +%p While you've been shopping, the stock levels for one or more of the products in your cart have reduced. Here's what's changed: + +%p{'ng-repeat' => "v in variants"} + %em {{ v.name_to_display }} - {{ v.unit_to_display }} + %span{'ng-if' => "v.count_on_hand == 0"} + is now out of stock. + %span{'ng-if' => "v.count_on_hand > 0"} + now only has {{ v.count_on_hand }} remaining. diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index 4c2ab8cb63..836b77b271 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -51,12 +51,11 @@ Spree::OrdersController.class_eval do [li.variant.id, {quantity: li.quantity, max_quantity: li.max_quantity, - on_hand: li.variant.on_hand}] + on_hand: wrap_json_infinity(li.variant.on_hand)}] end ] end - def update_distribution @order = current_order(true) @@ -135,4 +134,9 @@ Spree::OrdersController.class_eval do end end + # Rails to_json encodes Float::INFINITY as Infinity, which is not valid JSON + # Return it as a large integer (max 32 bit signed int) + def wrap_json_infinity(n) + n == Float::INFINITY ? 2147483647 : n + end end diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index 756be1d3ec..df7be3508d 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -69,6 +69,14 @@ describe Spree::OrdersController do it "returns a hash with variant id, quantity, max_quantity and stock on hand" do controller.stock_levels.should == {v.id => {quantity: 2, max_quantity: 3, on_hand: 4}} end + + describe "encoding Infinity" do + let!(:v) { create(:variant, on_demand: true, count_on_hand: 0) } + + it "encodes Infinity as a large, finite integer" do + controller.stock_levels.should == {v.id => {quantity: 2, max_quantity: 3, on_hand: 2147483647}} + end + end end end diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index c252a3f041..b0d5a42127 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -243,14 +243,13 @@ feature "As a consumer I want to shop with a distributor", js: true do variant.update_attributes! on_hand: 0 # -- Messaging - alert_message = accept_alert do - fill_in "variants[#{variant.id}]", with: '1' - wait_until { !cart_dirty } - end + fill_in "variants[#{variant.id}]", with: '1' + wait_until { !cart_dirty } - # TODO: This will be a modal - expect(alert_message).to be - puts alert_message + within(".out-of-stock-modal") do + page.should have_content "stock levels for one or more of the products in your cart have reduced" + page.should have_content "#{product.name} - #{variant.unit_to_display} is now out of stock." + end # -- Page updates # Update amount in cart @@ -274,14 +273,13 @@ feature "As a consumer I want to shop with a distributor", js: true do variant.update_attributes! on_hand: 0 # -- Messaging - alert_message = accept_alert do - fill_in "variant_attributes[#{variant.id}][max_quantity]", with: '1' - wait_until { !cart_dirty } - end + fill_in "variant_attributes[#{variant.id}][max_quantity]", with: '1' + wait_until { !cart_dirty } - # TODO: This will be a modal - expect(alert_message).to be - puts alert_message + within(".out-of-stock-modal") do + page.should have_content "stock levels for one or more of the products in your cart have reduced" + page.should have_content "#{product.name} - #{variant.unit_to_display} is now out of stock." + end # -- Page updates # Update amount in cart