diff --git a/Gemfile b/Gemfile index f28e8a8baa..6e48dd97d5 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,7 @@ gem 'i18n', '~> 0.6.11' gem 'nokogiri', '>= 1.6.7.1' gem 'pg' -gem 'spree', github: 'openfoodfoundation/spree', branch: '1-3-stable' +gem 'spree', github: 'openfoodfoundation/spree', branch: 'spree-upgrade-step1c' gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable' gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: '1-3-stable' @@ -87,6 +87,7 @@ gem "foundation-rails" gem 'foundation_rails_helper', github: 'willrjmarshall/foundation_rails_helper', branch: "rails3" gem 'jquery-rails' +gem 'jquery-migrate-rails' gem 'css_splitter' diff --git a/Gemfile.lock b/Gemfile.lock index a645196fc5..d346f7aa03 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,45 +23,48 @@ GIT GIT remote: git://github.com/openfoodfoundation/spree.git - revision: 6e3edfe40a5de8eba0095b2c5f3db9ea54c3afda - branch: 1-3-stable + revision: a4c439570b77afa50f9e36299811f293232bd281 + branch: spree-upgrade-step1c specs: - spree (1.3.6.beta) - spree_api (= 1.3.6.beta) - spree_cmd (= 1.3.6.beta) - spree_core (= 1.3.6.beta) - spree_promo (= 1.3.6.beta) - spree_sample (= 1.3.6.beta) - spree_api (1.3.6.beta) - spree_core (= 1.3.6.beta) + spree (1.3.99) + spree_api (= 1.3.99) + spree_cmd (= 1.3.99) + spree_core (= 1.3.99) + spree_dash (= 1.3.99) + spree_promo (= 1.3.99) + spree_sample (= 1.3.99) + spree_api (1.3.99) + spree_core (= 1.3.99) versioncake (= 0.4.0) - spree_cmd (1.3.6.beta) + spree_cmd (1.3.99) thor (>= 0.14.6) - spree_core (1.3.6.beta) - activemerchant (~> 1.34) + spree_core (1.3.99) + activemerchant (~> 1.50.0) acts_as_list (= 0.1.4) awesome_nested_set (= 2.1.5) aws-sdk (~> 1.11.1) cancan (= 1.6.8) deface (>= 0.9.0) ffaker (~> 1.15.0) - highline (= 1.6.18) - jquery-rails (~> 2.2.0) + highline (= 1.6.11) + jquery-rails (~> 2.0) json (>= 1.5.5) - kaminari (= 0.14.1) - money (= 5.1.1) + kaminari (= 0.13.0) + money (= 5.0.0) paperclip (~> 3.0) rabl (= 0.7.2) - rails (~> 3.2.16) + rails (~> 3.2.13) ransack (= 0.7.2) - select2-rails (= 3.5.9.3) - state_machine (= 1.1.2) + select2-rails (~> 3.2) + state_machine (= 1.2.0) stringex (~> 1.3.2) - truncate_html (~> 0.5.5) - spree_promo (1.3.6.beta) - spree_core (= 1.3.6.beta) - spree_sample (1.3.6.beta) - spree_core (= 1.3.6.beta) + spree_dash (1.3.99) + httparty (~> 0.8.1) + spree_core (= 1.3.99) + spree_promo (1.3.99) + spree_core (= 1.3.99) + spree_sample (1.3.99) + spree_core (= 1.3.99) GIT remote: git://github.com/spree/deface.git @@ -123,8 +126,8 @@ GEM sprockets (~> 2.2.1) active_model_serializers (0.8.3) activemodel (>= 3.0) - activemerchant (1.57.0) - activesupport (>= 3.2.14, < 5.1) + activemerchant (1.50.0) + activesupport (>= 3.2.14, < 5.0.0) builder (>= 2.1.2, < 4.0.0) i18n (>= 0.6.9) nokogiri (~> 1.4) @@ -167,9 +170,7 @@ GEM bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) blockenspiel (0.4.5) - bugsnag (1.5.2) - httparty (>= 0.6, < 1.0) - multi_json (~> 1.0) + bugsnag (4.1.0) builder (3.0.4) byebug (2.7.0) columnize (~> 0.3) @@ -189,7 +190,7 @@ GEM climate_control (0.0.3) activesupport (>= 3.0) cliver (0.3.2) - cocaine (0.5.7) + cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) coderay (1.0.9) coffee-rails (3.2.2) @@ -404,12 +405,12 @@ GEM zeus haml (4.0.4) tilt - highline (1.6.18) + highline (1.6.11) hike (1.2.3) http_parser.rb (0.5.3) - httparty (0.13.1) - json (~> 1.8) - multi_xml (>= 0.5.2) + httparty (0.8.3) + multi_json (~> 1.0) + multi_xml i18n (0.6.11) immigrant (0.1.6) activerecord (>= 3.0) @@ -417,16 +418,18 @@ GEM inflecto (0.0.2) ipaddress (0.8.0) journey (1.0.4) - jquery-rails (2.2.2) + jquery-migrate-rails (1.2.1) + jquery-rails (2.3.0) railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) json (1.8.3) json_spec (1.1.1) multi_json (~> 1.0) rspec (~> 2.0) - kaminari (0.14.1) + kaminari (0.13.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) + railties (>= 3.0.0) kgio (2.9.3) knapsack (1.5.1) rake @@ -449,8 +452,9 @@ GEM mini_portile2 (2.0.0) momentjs-rails (2.5.1) railties (>= 3.1) - money (5.1.1) - i18n (~> 0.6.0) + money (5.0.0) + i18n (~> 0.4) + json multi_json (1.12.1) multi_xml (0.5.5) newrelic_rpm (3.12.0.288) @@ -494,7 +498,7 @@ GEM activesupport (>= 2.3.14) multi_json (~> 1.0) rack (1.4.7) - rack-cache (1.2) + rack-cache (1.6.1) rack (>= 0.4) rack-livereload (0.3.15) rack @@ -521,7 +525,7 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) raindrops (0.13.0) - rake (10.4.2) + rake (11.1.2) ransack (0.7.2) actionpack (~> 3.0) activerecord (~> 3.0) @@ -571,7 +575,7 @@ GEM railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - select2-rails (3.5.9.3) + select2-rails (3.5.10) thor (~> 0.14) shoulda-matchers (1.1.0) activesupport (>= 3.0.0) @@ -583,7 +587,7 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - state_machine (1.1.2) + state_machine (1.2.0) stringex (1.3.3) therubyracer (0.12.0) libv8 (~> 3.16.14.0) @@ -601,7 +605,7 @@ GEM sprockets (>= 2.0.0) turn (0.8.3) ansi - tzinfo (0.3.44) + tzinfo (0.3.49) uglifier (2.7.1) execjs (>= 0.3.0) json (>= 1.8.0) @@ -682,6 +686,7 @@ DEPENDENCIES haml i18n (~> 0.6.11) immigrant + jquery-migrate-rails jquery-rails json_spec knapsack @@ -728,5 +733,8 @@ DEPENDENCIES wicked_pdf wkhtmltopdf-binary +RUBY VERSION + ruby 2.1.5p273 + BUNDLED WITH 1.12.5 diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index 0923e5721c..102cb237ca 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -6,6 +6,7 @@ // //= require jquery +//= require jquery-migrate-min //= require jquery_ujs //= require jquery-ui //= require shared/jquery-ui-timepicker-addon diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee index f21c96a27e..0a68ce9d94 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee @@ -27,7 +27,7 @@ angular.module("admin.enterprises") # Provide a callback for generating warning messages displayed before leaving the page. This is passed in # from a directive "nav-check" in the page - if we pass it here it will be called in the test suite, - # and on all new uses of this contoller, and we might not want that . + # and on all new uses of this contoller, and we might not want that. enterpriseNavCallback = -> if $scope.Enterprise.$dirty "Your changes to the enterprise are not saved yet." diff --git a/app/assets/javascripts/admin/enterprises/services/enterprises.js.coffee b/app/assets/javascripts/admin/enterprises/services/enterprises.js.coffee index 80db943689..44dfb503a5 100644 --- a/app/assets/javascripts/admin/enterprises/services/enterprises.js.coffee +++ b/app/assets/javascripts/admin/enterprises/services/enterprises.js.coffee @@ -4,16 +4,11 @@ angular.module("admin.enterprises").factory 'Enterprises', ($q, EnterpriseResour pristineByID: {} index: (params={}, callback=null) -> - includeBlank = !!params['includeBlank'] - delete params['includeBlank'] EnterpriseResource.index(params, (data) => for enterprise in data @enterprisesByID[enterprise.id] = enterprise @pristineByID[enterprise.id] = angular.copy(enterprise) - (callback || angular.noop)(data) - - data.unshift(blankOption()) if includeBlank data ) diff --git a/app/assets/javascripts/admin/index_utils/directives/ofn-select2.js.coffee b/app/assets/javascripts/admin/index_utils/directives/ofn-select2.js.coffee index d65341e6fe..6890589b9d 100644 --- a/app/assets/javascripts/admin/index_utils/directives/ofn-select2.js.coffee +++ b/app/assets/javascripts/admin/index_utils/directives/ofn-select2.js.coffee @@ -3,19 +3,42 @@ angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout, restrict: 'C' scope: data: "=" - minSearch: "@?" - text: "@?" + minSearch: "@" + text: "@" blank: "=?" filter: "=?" onSelecting: "=?" + multiple: '@' link: (scope, element, attrs, ngModel) -> $timeout -> - scope.text ||= 'name' - scope.filter ||= -> true + scope.text ?= 'name' + scope.multiple ?= false + scope.filter ?= -> true + + if scope.data.$promise + scope.data.$promise.then -> init() + else + init() + + element.on "select2-opening", scope.onSelecting || angular.noop + + attrs.$observe 'disabled', (value) -> + element.select2('enable', !value) + + ngModel.$formatters.push (value) -> + element.select2('val', value) + value + + ngModel.$parsers.push (value) -> + return value.split(",") if scope.multiple + value + + init = -> scope.data.unshift(scope.blank) if scope.blank? && typeof scope.blank is "object" item.name = $sanitize(item.name) for item in scope.data element.select2 + multiple: scope.multiple minimumResultsForSearch: scope.minSearch || 0 data: -> filtered = $filter('filter')(scope.data,scope.filter) @@ -24,12 +47,3 @@ angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout, item[scope.text] formatResult: (item) -> item[scope.text] - - element.on "select2-opening", scope.onSelecting || angular.noop - - attrs.$observe 'disabled', (value) -> - element.select2('enable', !value) - - ngModel.$formatters.push (value) -> - element.select2('val', value) - value diff --git a/app/assets/javascripts/admin/index_utils/services/dereferencer.js.coffee b/app/assets/javascripts/admin/index_utils/services/dereferencer.js.coffee index 4793c63034..fba6ef7908 100644 --- a/app/assets/javascripts/admin/index_utils/services/dereferencer.js.coffee +++ b/app/assets/javascripts/admin/index_utils/services/dereferencer.js.coffee @@ -3,7 +3,8 @@ angular.module("admin.indexUtils").factory 'Dereferencer', -> dereference: (array, data)-> if array for object, i in array - array[i] = data[object.id] + match = data[object.id] + array[i] = match if match? dereferenceAttr: (array, attr, data)-> if array diff --git a/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee b/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee index f105ebb0e5..f5d11fda58 100644 --- a/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee +++ b/app/assets/javascripts/admin/line_items/controllers/line_items_controller.js.coffee @@ -15,13 +15,13 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, LineItems.allSaved() || confirm(t("unsaved_changes_warning")) $scope.resetSelectFilters = -> - $scope.distributorFilter = blankOption().id - $scope.supplierFilter = blankOption().id - $scope.orderCycleFilter = blankOption().id + $scope.distributorFilter = 0 + $scope.supplierFilter = 0 + $scope.orderCycleFilter = 0 $scope.quickSearch = "" $scope.refreshData = -> - unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == "0" + unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0 $scope.startDate = OrderCycles.orderCyclesByID[$scope.orderCycleFilter].first_order $scope.endDate = OrderCycles.orderCyclesByID[$scope.orderCycleFilter].last_order @@ -29,9 +29,9 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, RequestMonitor.load $scope.lineItems = LineItems.index("q[order][state_not_eq]": "canceled", "q[order][completed_at_not_null]": "true", "q[order][completed_at_gt]": "#{parseDate($scope.startDate)}", "q[order][completed_at_lt]": "#{parseDate($scope.endDate)}") unless $scope.initialized - RequestMonitor.load $scope.distributors = Enterprises.index(includeBlank: true, action: "for_line_items", ams_prefix: "basic", "q[sells_in][]": ["own", "any"]) - RequestMonitor.load $scope.orderCycles = OrderCycles.index(includeBlank: true, ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{daysFromToday(-90)}") - RequestMonitor.load $scope.suppliers = Enterprises.index(includeBlank: true, action: "for_line_items", ams_prefix: "basic", "q[is_primary_producer_eq]": "true") + RequestMonitor.load $scope.distributors = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[sells_in][]": ["own", "any"]) + RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{daysFromToday(-90)}") + RequestMonitor.load $scope.suppliers = Enterprises.index(action: "for_line_items", ams_prefix: "basic", "q[is_primary_producer_eq]": "true") RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise]).then -> Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.enterprisesByID diff --git a/app/assets/javascripts/admin/line_items/filters/select_filter.js.coffee b/app/assets/javascripts/admin/line_items/filters/select_filter.js.coffee index 5195057663..6b6428c010 100644 --- a/app/assets/javascripts/admin/line_items/filters/select_filter.js.coffee +++ b/app/assets/javascripts/admin/line_items/filters/select_filter.js.coffee @@ -2,7 +2,7 @@ angular.module("admin.lineItems").filter "selectFilter", (blankOption, RequestMo return (lineItems,selectedSupplier,selectedDistributor,selectedOrderCycle) -> filtered = [] unless RequestMonitor.loading - filtered.push lineItem for lineItem in lineItems when (angular.equals(selectedSupplier,"0") || lineItem.supplier.id == selectedSupplier) && - (angular.equals(selectedDistributor,"0") || lineItem.order.distributor.id == selectedDistributor) && - (angular.equals(selectedOrderCycle,"0") || lineItem.order.order_cycle.id == selectedOrderCycle) + filtered.push lineItem for lineItem in lineItems when (angular.equals(selectedSupplier,0) || lineItem.supplier.id == selectedSupplier) && + (angular.equals(selectedDistributor,0) || lineItem.order.distributor.id == selectedDistributor) && + (angular.equals(selectedOrderCycle,0) || lineItem.order.order_cycle.id == selectedOrderCycle) filtered diff --git a/app/assets/javascripts/admin/util.js.erb b/app/assets/javascripts/admin/util.js.erb index bc963d4612..4a8c526414 100644 --- a/app/assets/javascripts/admin/util.js.erb +++ b/app/assets/javascripts/admin/util.js.erb @@ -30,8 +30,16 @@ show_flash_error = function(message) { } $(document).ready(function(){ - $('a.close').click(function(event){ - event.preventDefault(); - $(this).parent().slideUp(250); - }); + $('a.close').click(function(event){ + event.preventDefault(); + $(this).parent().slideUp(250); + }); + + // Spree locates hidden with prev(), which with our current version of jQuery + // does not locate the hidden field, resulting in the delete failing. This + // handler updates the hidden field, fixing the problem. + $('body').on('click', 'a.remove_fields', function() { + $(this).next("input[type=hidden]").val("1"); + return false; + }); }); diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb index 377186b604..f2c9552c4a 100644 --- a/app/controllers/admin/enterprises_controller.rb +++ b/app/controllers/admin/enterprises_controller.rb @@ -2,6 +2,10 @@ require 'open_food_network/referer_parser' module Admin class EnterprisesController < ResourceController + # These need to run before #load_resource so that @object is initialised with sanitised values + prepend_before_filter :override_owner, only: :create + prepend_before_filter :override_sells, only: :create + before_filter :load_enterprise_set, :only => :index before_filter :load_countries, :except => [:index, :register, :check_permalink] before_filter :load_methods_and_fees, :only => [:edit, :update] @@ -9,8 +13,6 @@ module Admin before_filter :load_taxons, :only => [:new, :edit, :update, :create] before_filter :check_can_change_sells, only: :update before_filter :check_can_change_bulk_sells, only: :bulk_update - before_filter :override_owner, only: :create - before_filter :override_sells, only: :create before_filter :check_can_change_owner, only: :update before_filter :check_can_change_bulk_owner, only: :bulk_update before_filter :check_can_change_managers, only: :update @@ -115,8 +117,8 @@ module Admin def build_resource_with_address enterprise = build_resource_without_address - enterprise.address = Spree::Address.new - enterprise.address.country = Spree::Country.find_by_id(Spree::Config[:default_country_id]) + enterprise.address ||= Spree::Address.new + enterprise.address.country ||= Spree::Country.find_by_id(Spree::Config[:default_country_id]) enterprise end alias_method_chain :build_resource, :address @@ -269,9 +271,10 @@ module Admin # Overriding method on Spree's resource controller def location_after_save referer_path = OpenFoodNetwork::RefererParser::path(request.referer) - refered_from_edit = referer_path =~ /\/edit$/ - if params[:enterprise].key?(:producer_properties_attributes) && !refered_from_edit - main_app.admin_enterprises_path + refered_from_producer_properties = referer_path =~ /\/producer_properties$/ + + if refered_from_producer_properties + main_app.admin_enterprise_producer_properties_path(@enterprise) else main_app.edit_admin_enterprise_path(@enterprise) end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 7dfd404b69..c5eb745c05 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -20,6 +20,11 @@ class ApplicationController < ActionController::Base private + def action + params[:action].to_sym + end + + def require_distributor_chosen unless @distributor = current_distributor redirect_to spree.root_path diff --git a/app/controllers/base_controller.rb b/app/controllers/base_controller.rb index 58bf679dc3..36084c0225 100644 --- a/app/controllers/base_controller.rb +++ b/app/controllers/base_controller.rb @@ -1,8 +1,13 @@ +require 'spree/core/controller_helpers/respond_with_decorator' require 'open_food_network/tag_rule_applicator' class BaseController < ApplicationController include Spree::Core::ControllerHelpers + include Spree::Core::ControllerHelpers::Auth + include Spree::Core::ControllerHelpers::Common + include Spree::Core::ControllerHelpers::Order include Spree::Core::ControllerHelpers::RespondWith + include EnterprisesHelper include OrderCyclesHelper diff --git a/app/controllers/spree/admin/adjustments_controller_decorator.rb b/app/controllers/spree/admin/adjustments_controller_decorator.rb index 12c9ae2c60..d3059b4804 100644 --- a/app/controllers/spree/admin/adjustments_controller_decorator.rb +++ b/app/controllers/spree/admin/adjustments_controller_decorator.rb @@ -1,7 +1,7 @@ module Spree module Admin AdjustmentsController.class_eval do - before_filter :set_included_tax, only: [:create, :update] + prepend_before_filter :set_included_tax, only: [:create, :update] before_filter :set_default_tax_rate, only: :edit diff --git a/app/controllers/spree/admin/base_controller_decorator.rb b/app/controllers/spree/admin/base_controller_decorator.rb index 9888967f58..d5e62469cb 100644 --- a/app/controllers/spree/admin/base_controller_decorator.rb +++ b/app/controllers/spree/admin/base_controller_decorator.rb @@ -1,3 +1,5 @@ +require 'spree/core/controller_helpers/respond_with_decorator' + Spree::Admin::BaseController.class_eval do before_filter :warn_invalid_order_cycles diff --git a/app/controllers/spree/admin/products_controller_decorator.rb b/app/controllers/spree/admin/products_controller_decorator.rb index 5b1bb347a1..7929aa1df6 100644 --- a/app/controllers/spree/admin/products_controller_decorator.rb +++ b/app/controllers/spree/admin/products_controller_decorator.rb @@ -8,7 +8,6 @@ Spree::Admin::ProductsController.class_eval do before_filter :load_spree_api_key, :only => [:bulk_edit, :variant_overrides] before_filter :strip_new_properties, only: [:create, :update] - alias_method :location_after_save_original, :location_after_save respond_to :json, :only => :clone @@ -53,14 +52,17 @@ Spree::Admin::ProductsController.class_eval do protected - def location_after_save + + def location_after_save_with_bulk_edit referer_path = OpenFoodNetwork::RefererParser::path(request.referer) + if referer_path == '/admin/products/bulk_edit' bulk_edit_admin_products_url else - location_after_save_original + location_after_save_without_bulk_edit end end + alias_method_chain :location_after_save, :bulk_edit def collection # This method is copied directly from the spree product controller, except where we narrow the search below with the managed_by search to support diff --git a/app/controllers/spree/admin/resource_controller_decorator.rb b/app/controllers/spree/admin/resource_controller_decorator.rb new file mode 100644 index 0000000000..cb789d7330 --- /dev/null +++ b/app/controllers/spree/admin/resource_controller_decorator.rb @@ -0,0 +1,16 @@ +module AuthorizeOnLoadResource + def load_resource + super + + if member_action? + # If we don't have access, clear the object + unless can? action, @object + instance_variable_set("@#{object_name}", nil) + end + + authorize! action, @object + end + end +end + +Spree::Admin::ResourceController.send(:prepend, AuthorizeOnLoadResource) diff --git a/app/controllers/spree/api/users_controller.rb b/app/controllers/spree/api/users_controller.rb new file mode 100644 index 0000000000..74f83f6709 --- /dev/null +++ b/app/controllers/spree/api/users_controller.rb @@ -0,0 +1,7 @@ +module Spree + module Api + class UsersController < Spree::Api::BaseController + respond_to :json + end + end +end diff --git a/app/controllers/spree/orders_controller_decorator.rb b/app/controllers/spree/orders_controller_decorator.rb index 2c0ff8562c..dd4f2eba81 100644 --- a/app/controllers/spree/orders_controller_decorator.rb +++ b/app/controllers/spree/orders_controller_decorator.rb @@ -40,7 +40,6 @@ Spree::OrdersController.class_eval do if @order.update_attributes(params[:order]) @order.line_items = @order.line_items.select {|li| li.quantity > 0 } - @order.restart_checkout_flow render :edit and return unless apply_coupon_code diff --git a/app/helpers/spree/admin/base_helper_decorator.rb b/app/helpers/spree/admin/base_helper_decorator.rb index 86e77431ba..5398cee35f 100644 --- a/app/helpers/spree/admin/base_helper_decorator.rb +++ b/app/helpers/spree/admin/base_helper_decorator.rb @@ -1,22 +1,6 @@ module Spree module Admin module BaseHelper - # Add url option to pass in link URL - def link_to_remove_fields(name, f, options = {}) - name = '' if options[:no_text] - options[:class] = '' unless options[:class] - options[:class] += 'no-text' if options[:no_text] - - url = if f.object.persisted? - options[:url] || [:admin, f.object] - else - '#' - end - - link_to_with_icon('icon-trash', name, url, :class => "remove_fields #{options[:class]}", :data => {:action => 'remove'}, :title => t(:remove)) + f.hidden_field(:_destroy) - end - - def preference_field_tag_with_files(name, value, options) if options[:type] == :file file_field_tag name, preference_field_options(options) @@ -25,6 +9,20 @@ module Spree end end alias_method_chain :preference_field_tag, :files + + + # Add support for options[:html], allowing additional HTML attributes + def link_to_remove_fields(name, f, options = {}) + name = '' if options[:no_text] + options[:class] = '' unless options[:class] + options[:class] += 'no-text with-tip' if options[:no_text] + + html_options = {class: "remove_fields #{options[:class]}", data: {action: 'remove'}, title: t(:remove)} + html_options.merge!(options[:html]) if options.key? :html + + link_to_with_icon('icon-trash', name, '#', html_options) + f.hidden_field(:_destroy) + end + end end end diff --git a/app/helpers/spree/admin/navigation_helper_decorator.rb b/app/helpers/spree/admin/navigation_helper_decorator.rb index eb210ef482..d7d0bd2370 100644 --- a/app/helpers/spree/admin/navigation_helper_decorator.rb +++ b/app/helpers/spree/admin/navigation_helper_decorator.rb @@ -4,14 +4,14 @@ module Spree # Make it so that the Reports admin tab can be enabled/disabled through the cancan # :report resource, since it does not have a corresponding resource class (unlike # eg. Spree::Product). - def klass_for_with_sym_fallback(name) - klass = klass_for_without_sym_fallback(name) - klass ||= name.singularize.to_sym - klass = :overview if klass == :dashboard - klass = Spree::Order if klass == :bulk_order_management - klass - end - alias_method_chain :klass_for, :sym_fallback + # def klass_for_with_sym_fallback(name) + # klass = klass_for_without_sym_fallback(name) + # klass ||= name.singularize.to_sym + # klass = :overview if klass == :dashboard + # klass = Spree::Order if klass == :bulk_order_management + # klass + # end + # alias_method_chain :klass_for, :sym_fallback end end end diff --git a/app/mailers/spree/base_mailer_decorator.rb b/app/mailers/spree/base_mailer_decorator.rb index 339abd8901..949f51d2f0 100644 --- a/app/mailers/spree/base_mailer_decorator.rb +++ b/app/mailers/spree/base_mailer_decorator.rb @@ -6,6 +6,13 @@ Spree::BaseMailer.class_eval do layout 'mailer' protected + + def from_address + Spree::MailMethod.current.andand.preferred_mails_from || + 'test@example.com' + end + + def roadie_options # This lets us specify assets using relative paths in email templates super.merge(url_options: {host: URI(spree.root_url).host }) diff --git a/app/mailers/spree/order_mailer_decorator.rb b/app/mailers/spree/order_mailer_decorator.rb index 016b61efa4..13f014d5a0 100644 --- a/app/mailers/spree/order_mailer_decorator.rb +++ b/app/mailers/spree/order_mailer_decorator.rb @@ -3,6 +3,13 @@ Spree::OrderMailer.class_eval do helper CheckoutHelper helper SpreeCurrencyHelper + def cancel_email(order, resend = false) + @order = find_order(order) + subject = (resend ? "[#{t(:resend).upcase}] " : '') + subject += "#{Spree::Config[:site_name]} #{t('order_mailer.cancel_email.subject')} ##{order.number}" + mail(to: order.email, from: from_address, subject: subject) + end + def confirm_email_for_customer(order, resend = false) find_order(order) # Finds an order instance from an id subject = (resend ? "[#{t(:resend).upcase}] " : '') @@ -31,4 +38,8 @@ Spree::OrderMailer.class_eval do :subject => subject, :reply_to => @order.distributor.email) end + + def find_order(order) + @order = order.respond_to?(:id) ? order : Spree::Order.find(order) + end end diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 80414d5116..5460ecc94d 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -78,6 +78,7 @@ class Enterprise < ActiveRecord::Base validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? } validates_length_of :description, :maximum => 255 + before_save :confirmation_check, if: lambda { email_changed? } before_validation :initialize_permalink, if: lambda { permalink.nil? } @@ -93,6 +94,7 @@ class Enterprise < ActiveRecord::Base after_rollback :restore_permalink + scope :by_name, order('name') scope :visible, where(visible: true) scope :confirmed, where('confirmed_at IS NOT NULL') diff --git a/app/models/enterprise_fee.rb b/app/models/enterprise_fee.rb index d1d0816340..ff118cf0aa 100644 --- a/app/models/enterprise_fee.rb +++ b/app/models/enterprise_fee.rb @@ -16,6 +16,7 @@ class EnterpriseFee < ActiveRecord::Base calculated_adjustments + attr_accessible :enterprise_id, :fee_type, :name, :tax_category_id, :calculator_type, :inherits_tax_category FEE_TYPES = %w(packing transport admin sales fundraising) diff --git a/app/models/enterprise_group.rb b/app/models/enterprise_group.rb index 63eb63f0b3..8b96ca9163 100644 --- a/app/models/enterprise_group.rb +++ b/app/models/enterprise_group.rb @@ -58,14 +58,14 @@ class EnterpriseGroup < ActiveRecord::Base } def set_unused_address_fields - address.firstname = address.lastname = 'unused' if address.present? + address.firstname = address.lastname = 'unused' end def set_undefined_address_fields - return unless address.present? address.phone.present? || address.phone = 'undefined' address.address1.present? || address.address1 = 'undefined' address.city.present? || address.city = 'undefined' + address.state.present? || address.state = address.country.states.first address.zipcode.present? || address.zipcode = 'undefined' end diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index c2bd99bcdb..b10c781fac 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -110,12 +110,12 @@ class AbilityDecorator def add_product_management_abilities(user) # Enterprise User can only access products that they are a supplier for can [:create], Spree::Product - can [:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], Spree::Product do |product| + can [:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :delete, :destroy], Spree::Product do |product| OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? product.supplier end can [:create], Spree::Variant - can [:admin, :index, :read, :edit, :update, :search, :destroy], Spree::Variant do |variant| + can [:admin, :index, :read, :edit, :update, :search, :delete, :destroy], Spree::Variant do |variant| OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier end diff --git a/app/models/spree/calculator/flat_percent_item_total_decorator.rb b/app/models/spree/calculator/flat_percent_item_total_decorator.rb new file mode 100644 index 0000000000..9012261dab --- /dev/null +++ b/app/models/spree/calculator/flat_percent_item_total_decorator.rb @@ -0,0 +1,9 @@ +module Spree + Calculator::FlatPercentItemTotal.class_eval do + def compute(object) + item_total = line_items_for(object).map(&:amount).sum + value = item_total * BigDecimal(self.preferred_flat_percent.to_s) / 100.0 + (value * 100).round.to_f / 100 + end + end +end diff --git a/app/models/spree/calculator/flexi_rate_decorator.rb b/app/models/spree/calculator/flexi_rate_decorator.rb new file mode 100644 index 0000000000..c4ef6183c2 --- /dev/null +++ b/app/models/spree/calculator/flexi_rate_decorator.rb @@ -0,0 +1,19 @@ +module Spree + Calculator::FlexiRate.class_eval do + def compute(object) + sum = 0 + max = self.preferred_max_items.to_i + items_count = line_items_for(object).map(&:quantity).sum + items_count.times do |i| + # check max value to avoid divide by 0 errors + if (max == 0 && i == 0) || (max > 0) && (i % max == 0) + sum += self.preferred_first_item.to_f + else + sum += self.preferred_additional_item.to_f + end + end + + sum + end + end +end diff --git a/app/models/spree/calculator/per_item_decorator.rb b/app/models/spree/calculator/per_item_decorator.rb new file mode 100644 index 0000000000..ebaaf6fc1c --- /dev/null +++ b/app/models/spree/calculator/per_item_decorator.rb @@ -0,0 +1,15 @@ +module Spree + Calculator::PerItem.class_eval do + def compute(object=nil) + return 0 if object.nil? + self.preferred_amount * line_items_for(object).reduce(0) do |sum, value| + if matching_products.blank? || matching_products.include?(value.product) + value_to_add = value.quantity + else + value_to_add = 0 + end + sum + value_to_add + end + end + end +end diff --git a/app/models/spree/calculator_decorator.rb b/app/models/spree/calculator_decorator.rb new file mode 100644 index 0000000000..f8be4d00ef --- /dev/null +++ b/app/models/spree/calculator_decorator.rb @@ -0,0 +1,18 @@ +module Spree + Calculator.class_eval do + + + private + + # Given an object which might be an Order or a LineItem (amongst + # others), return a collection of line items. + def line_items_for(object) + if object.respond_to? :line_items + object.line_items + else + [object] + end + end + + end +end diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index f6128a736d..c62f114177 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -35,7 +35,7 @@ Spree::Order.class_eval do order.payment_required? } go_to_state :confirm, :if => lambda { |order| order.confirmation_required? } - go_to_state :complete, :if => lambda { |order| (order.payment_required? && order.has_unprocessed_payments?) || !order.payment_required? } + go_to_state :complete remove_transition :from => :delivery, :to => :confirm end diff --git a/app/models/spree/payment_method_decorator.rb b/app/models/spree/payment_method_decorator.rb index 4a718dfc16..fb5faaef4c 100644 --- a/app/models/spree/payment_method_decorator.rb +++ b/app/models/spree/payment_method_decorator.rb @@ -1,4 +1,6 @@ Spree::PaymentMethod.class_eval do + Spree::PaymentMethod::DISPLAY = [:both, :front_end, :back_end] + acts_as_taggable has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id' diff --git a/app/serializers/api/currency_config_serializer.rb b/app/serializers/api/currency_config_serializer.rb index ab17af8715..100a4a0b84 100644 --- a/app/serializers/api/currency_config_serializer.rb +++ b/app/serializers/api/currency_config_serializer.rb @@ -1,5 +1,5 @@ class Api::CurrencyConfigSerializer < ActiveModel::Serializer - attributes :currency, :display_currency, :symbol, :symbol_position, :hide_cents, :decimal_mark, :thousands_separator + attributes :currency, :display_currency, :symbol, :symbol_position, :hide_cents def currency Spree::Config[:currency] @@ -13,20 +13,12 @@ class Api::CurrencyConfigSerializer < ActiveModel::Serializer ::Money.new(1, Spree::Config[:currency]).symbol end - def symbol_position + def symbol_position Spree::Config[:currency_symbol_position] end - def hide_cents + def hide_cents Spree::Config[:hide_cents] end - def decimal_mark - Spree::Config[:currency_decimal_mark] - end - - def thousands_separator - Spree::Config[:currency_thousands_separator] - end - end diff --git a/app/views/admin/producer_properties/_producer_property_fields.html.haml b/app/views/admin/producer_properties/_producer_property_fields.html.haml index 314cbfc31a..6fe0b1d7ad 100644 --- a/app/views/admin/producer_properties/_producer_property_fields.html.haml +++ b/app/views/admin/producer_properties/_producer_property_fields.html.haml @@ -12,4 +12,4 @@ = f.text_field :value, :class => 'autocomplete' %td.actions - unless @enterprise.producer_properties.empty? - = link_to_remove_fields t(:remove), f, no_text: true, url: (f.object.persisted? && main_app.admin_enterprise_producer_property_path(@enterprise, f.object)) + = link_to_remove_fields t(:remove), f, no_text: true, url: (f.object.persisted? && main_app.admin_enterprise_producer_property_path(@enterprise, f.object)), html: {"onclick" => "if(typeof(enterprise_form) != 'undefined') { angular.element(enterprise_form).scope().setFormDirty() }".html_safe} diff --git a/app/views/spree/admin/orders/bulk_management.html.haml b/app/views/spree/admin/orders/bulk_management.html.haml index 520d2376a4..70de7fdd89 100644 --- a/app/views/spree/admin/orders/bulk_management.html.haml +++ b/app/views/spree/admin/orders/bulk_management.html.haml @@ -31,17 +31,17 @@ %label{ :for => 'supplier_filter' } = t("admin.producer") %br - %select{ :class => "three columns alpha", :id => 'supplier_filter', 'select2-min-search' => 5, 'ng-model' => 'supplierFilter', 'ng-options' => 's.id as s.name for s in suppliers' } + %input#supplier_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'suppliers', blank: "{ id: 0, name: 'All' }", ng: { model: 'supplierFilter' } } .filter_select{ :class => "three columns" } %label{ :for => 'distributor_filter' } = t("admin.shop") %br - %select{ :class => "three columns alpha", :id => 'distributor_filter', 'select2-min-search' => 5, 'ng-model' => 'distributorFilter', 'ng-options' => 'd.id as d.name for d in distributors'} + %input#distributor_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'distributors', blank: "{ id: 0, name: 'All' }", ng: { model: 'distributorFilter' } } .filter_select{ :class => "three columns" } %label{ :for => 'order_cycle_filter' } = t("admin.order_cycle") %br - %select{ :class => "three columns alpha", :id => 'order_cycle_filter', 'select2-min-search' => 5, 'ng-model' => 'orderCycleFilter', 'ng-options' => 'oc.id as oc.name for oc in orderCycles', 'confirm-change' => "confirmRefresh()", 'ng-change' => 'refreshData()'} + %input#order_cycle_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'orderCycles', blank: "{ id: 0, name: 'All' }", on: { selecting: "confirmRefresh" }, ng: { model: 'orderCycleFilter', change: 'refreshData()' } } .filter_clear{ :class => "two columns omega" } %label{ :for => 'clear_all_filters' } %br diff --git a/config/initializers/spree.rb b/config/initializers/spree.rb index 30182ef63a..f439e779cf 100644 --- a/config/initializers/spree.rb +++ b/config/initializers/spree.rb @@ -8,6 +8,7 @@ require 'spree/product_filters' +require 'spree/core/calculated_adjustments_decorator' require "#{Rails.root}/app/models/spree/payment_method_decorator" require "#{Rails.root}/app/models/spree/gateway_decorator" diff --git a/config/locales/en.yml b/config/locales/en.yml index ba2b1acab6..2211243bda 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1074,6 +1074,9 @@ Please follow the instructions there to make your enterprise visible on the Open validation_msg_is_associated_with_an_exising_customer: "is associated with an existing customer" spree: + date_picker: + format: ! '%Y-%m-%d' + js_format: 'yy-mm-dd' zipcode: Postcode shipment_states: backorder: backorder diff --git a/lib/open_food_network/referer_parser.rb b/lib/open_food_network/referer_parser.rb index b90ef21829..20be289f44 100644 --- a/lib/open_food_network/referer_parser.rb +++ b/lib/open_food_network/referer_parser.rb @@ -5,13 +5,11 @@ module OpenFoodNetwork end def self.parse_uri(string) - begin - # TODO: make this operation obsolete by fixing URLs generated by AngularJS - string.sub!('##', '#') - URI(string) - rescue URI::InvalidURIError - nil - end + # TODO: make this operation obsolete by fixing URLs generated by AngularJS + string.sub!('##', '#') + URI(string) + rescue URI::InvalidURIError + nil end end end diff --git a/lib/spree/core/calculated_adjustments_decorator.rb b/lib/spree/core/calculated_adjustments_decorator.rb new file mode 100644 index 0000000000..6a42eb68c5 --- /dev/null +++ b/lib/spree/core/calculated_adjustments_decorator.rb @@ -0,0 +1,14 @@ +module Spree + module Core + module CalculatedAdjustments + module ClassMethods + def calculated_adjustments_with_explicit_class_name + calculated_adjustments_without_explicit_class_name + # Class name is mis-inferred outside of Spree namespace + has_one :calculator, as: :calculable, dependent: :destroy, class_name: 'Spree::Calculator' + end + alias_method_chain :calculated_adjustments, :explicit_class_name + end + end + end +end diff --git a/lib/spree/core/controller_helpers/respond_with_decorator.rb b/lib/spree/core/controller_helpers/respond_with_decorator.rb new file mode 100644 index 0000000000..4910591b9c --- /dev/null +++ b/lib/spree/core/controller_helpers/respond_with_decorator.rb @@ -0,0 +1,26 @@ +module ActionController + class Base + def respond_with(*resources, &block) + raise "In order to use respond_with, first you need to declare the formats your " << + "controller responds to in the class level" if self.class.mimes_for_respond_to.empty? + + if collector = retrieve_collector_from_mimes(&block) + options = resources.size == 1 ? {} : resources.extract_options! + + # Fix spree issues #3531 and #2210 (patch provided by leiyangyou) + if defined_response = collector.response and !(Spree::BaseController.spree_responders[self.class.to_s.to_sym].try(:[], action_name.to_sym)) + if action = options.delete(:action) + render :action => action + else + defined_response.call + end + else + # The action name is needed for processing + options.merge!(:action_name => action_name.to_sym) + # If responder is not specified then pass in Spree::Responder + (options.delete(:responder) || Spree::Responder).call(self, resources, options) + end + end + end + end +end diff --git a/lib/spree/money_decorator.rb b/lib/spree/money_decorator.rb index 3479bbd9a2..755041df0e 100644 --- a/lib/spree/money_decorator.rb +++ b/lib/spree/money_decorator.rb @@ -6,7 +6,18 @@ Spree::Money.class_eval do end def rounded - @options[:no_cents] = true if @money.amount % 1 == 0 + @options[:no_cents] = true if @money.dollars % 1 == 0 to_s end + + def to_html(options = { :html => true }) + output = @money.format(@options.merge(options)) + if options[:html] + # 1) prevent blank, breaking spaces + # 2) prevent escaping of HTML character entities + output = output.sub(" ", " ").html_safe + end + output + end + end diff --git a/spec/controllers/admin/enterprises_controller_spec.rb b/spec/controllers/admin/enterprises_controller_spec.rb index 05498010bb..94282e6c2c 100644 --- a/spec/controllers/admin/enterprises_controller_spec.rb +++ b/spec/controllers/admin/enterprises_controller_spec.rb @@ -28,6 +28,7 @@ module Admin spree_put :create, enterprise_params enterprise = Enterprise.find_by_name 'zzz' + response.should redirect_to edit_admin_enterprise_path enterprise distributor_manager.enterprise_roles.where(enterprise_id: enterprise).first.should be end @@ -37,15 +38,17 @@ module Admin spree_put :create, enterprise_params enterprise = Enterprise.find_by_name 'zzz' + response.should redirect_to edit_admin_enterprise_path enterprise admin_user.enterprise_roles.where(enterprise_id: enterprise).should be_empty end - it "overrides the owner_id submitted by the user unless current_user is super admin" do + it "overrides the owner_id submitted by the user (when not super admin)" do controller.stub spree_current_user: distributor_manager enterprise_params[:enterprise][:owner_id] = user spree_put :create, enterprise_params enterprise = Enterprise.find_by_name 'zzz' + response.should redirect_to edit_admin_enterprise_path enterprise distributor_manager.enterprise_roles.where(enterprise_id: enterprise).first.should be end @@ -58,6 +61,7 @@ module Admin spree_put :create, enterprise_params enterprise = Enterprise.find_by_name 'zzz' + response.should redirect_to edit_admin_enterprise_path enterprise enterprise.sells.should == 'any' end @@ -68,6 +72,7 @@ module Admin spree_put :create, enterprise_params enterprise = Enterprise.find_by_name 'zzz' + response.should redirect_to edit_admin_enterprise_path enterprise enterprise.sells.should == 'none' end @@ -80,6 +85,7 @@ module Admin spree_put :create, enterprise_params enterprise = Enterprise.find_by_name 'zzz' + response.should redirect_to edit_admin_enterprise_path enterprise enterprise.sells.should == 'none' end end diff --git a/spec/controllers/spree/api/variants_controller_spec.rb b/spec/controllers/spree/api/variants_controller_spec.rb index 5fb9f2f2a0..39c6439999 100644 --- a/spec/controllers/spree/api/variants_controller_spec.rb +++ b/spec/controllers/spree/api/variants_controller_spec.rb @@ -47,7 +47,7 @@ module Spree spree_delete :soft_delete, {variant_id: variant.to_param, product_id: product.to_param, format: :json} response.status.should == 204 lambda { variant.reload }.should_not raise_error - variant.deleted_at.should_not be_nil + variant.deleted_at.should be_present end it "is denied access to soft deleting another enterprises' variant" do diff --git a/spec/factories.rb b/spec/factories.rb index 9875d22652..d4193c11aa 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -319,10 +319,6 @@ end FactoryGirl.modify do - factory :base_product do - unit_value 1 - unit_description '' - end factory :product do primary_taxon { Spree::Taxon.first || FactoryGirl.create(:taxon) } end @@ -336,12 +332,15 @@ FactoryGirl.modify do primary_taxon { Spree::Taxon.first || FactoryGirl.create(:taxon) } on_hand 3 + unit_value 1 + unit_description '' + variant_unit 'weight' variant_unit_scale 1 variant_unit_name '' end - factory :base_variant do + factory :variant do unit_value 1 unit_description '' end diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index b436c0c3ee..c051c9eade 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -77,7 +77,7 @@ feature %q{ visit '/admin/enterprises' within "tr.enterprise-#{@enterprise.id}" do - all("a", text: 'Edit Profile').first.click + first("a", text: 'Edit Profile').trigger 'click' end fill_in 'enterprise_name', :with => 'Eaterprises' @@ -210,8 +210,8 @@ feature %q{ fill_in 'enterprise_producer_properties_attributes_0_value', with: "NASAA 12345" click_button 'Update' - # Then I should be returned to the enterprises page - page.should have_selector '#listing_enterprises a', text: s.name + # Then I should remain on the producer properties page + expect(current_path).to eq main_app.admin_enterprise_producer_properties_path(s) # And the producer should have the property s.producer_properties(true).count.should == 1 @@ -233,8 +233,8 @@ feature %q{ fill_in 'enterprise_producer_properties_attributes_0_value', with: "Shininess" click_button 'Update' - # Then I should be returned to the enterprises - page.should have_selector '#listing_enterprises a', text: s.name + # Then I should remain on the producer properties page + expect(current_path).to eq main_app.admin_enterprise_producer_properties_path(s) # And the property should be updated s.producer_properties(true).count.should == 1 @@ -254,9 +254,10 @@ feature %q{ # And I remove the property page.should have_field 'enterprise_producer_properties_attributes_0_property_name', with: 'Certified Organic' within("#spree_producer_property_#{pp.id}") { page.find('a.remove_fields').click } + click_button 'Update' # Then the property should have been removed - page.should_not have_selector '#progress' + expect(current_path).to eq main_app.admin_enterprise_producer_properties_path(s) page.should_not have_field 'enterprise_producer_properties_attributes_0_property_name', with: 'Certified Organic' s.producer_properties(true).should be_empty end @@ -438,7 +439,10 @@ feature %q{ end within("#spree_producer_property_#{pp.id}") { page.find('a.remove_fields').click } - page.should_not have_selector '#progress' + + click_button 'Update' + + expect(page).to have_content 'Enterprise "First Supplier" has been successfully updated!' supplier1.producer_properties(true).should be_empty end end diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 74b2e88453..212fafd026 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -409,11 +409,11 @@ feature %q{ end - scenario "updating many order cycle opening/closing times at once" do + scenario "updating many order cycle opening/closing times at once", js: true do # Given three order cycles oc1 = create(:simple_order_cycle) oc2 = create(:simple_order_cycle) - oc3 = create(:simple_order_cycle) + oc3 = create(:simple_order_cycle, orders_open_at: Time.zone.local(2040, 12, 12, 12, 12, 12)) # When I go to the order cycles page login_to_admin_section @@ -430,7 +430,28 @@ feature %q{ all('input').last.set '2040-12-01 12:00:03' end + # And I fill in a time using the datepicker within("tr.order-cycle-#{oc3.id}") do + # When I trigger the datepicker + find('img.ui-datepicker-trigger', match: :first).click + end + + within("#ui-datepicker-div") do + # Then it should display the correct date/time + expect(page).to have_selector 'span.ui-datepicker-month', text: 'DECEMBER' + expect(page).to have_selector 'span.ui-datepicker-year', text: '2040' + expect(page).to have_selector 'a.ui-state-active', text: '12' + + # When I fill in a new date/time + click_link '1' + click_button 'Done' + end + + within("tr.order-cycle-#{oc3.id}") do + # Then that date/time should appear on the form + expect(all('input').first.value).to eq '2040-12-01 00:00' + + # Manually fill out time all('input').first.set '2040-12-01 12:00:04' all('input').last.set '2040-12-01 12:00:05' end diff --git a/spec/features/admin/products_spec.rb b/spec/features/admin/products_spec.rb index 2aafc82b02..445844d97b 100644 --- a/spec/features/admin/products_spec.rb +++ b/spec/features/admin/products_spec.rb @@ -39,6 +39,7 @@ feature %q{ click_button 'Create' + expect(current_path).to eq spree.bulk_edit_admin_products_path flash_message.should == 'Product "A new product !!!" has been successfully created!' product = Spree::Product.find_by_name('A new product !!!') product.supplier.should == @supplier @@ -56,22 +57,6 @@ feature %q{ product.group_buy.should be_false product.master.option_values.map(&:name).should == ['5kg'] product.master.options_text.should == "5kg" - - # Distributors - visit spree.product_distributions_admin_product_path(product) - - check @distributors[0].name - select2_select @enterprise_fees[0].name, :from => 'product_product_distributions_attributes_0_enterprise_fee_id' - check @distributors[2].name - select2_select @enterprise_fees[2].name, :from => 'product_product_distributions_attributes_2_enterprise_fee_id' - - click_button 'Update' - - product.reload - product.distributors.should match_array [@distributors[0], @distributors[2]] - - - product.product_distributions.map { |pd| pd.enterprise_fee }.should match_array [@enterprise_fees[0], @enterprise_fees[2]] end scenario "making a product into a group buy product" do @@ -185,7 +170,7 @@ feature %q{ scenario "deleting product properties", js: true do # Given a product with a property - p = create(:simple_product, supplier: @supplier) + p = create(:simple_product, supplier: @supplier2) p.set_property('fooprop', 'fooval') # When I navigate to the product properties page @@ -195,11 +180,12 @@ feature %q{ # And I delete the property page.all('a.remove_fields').first.click - wait_until { p.reload.property('fooprop').nil? } + click_button 'Update' # Then the property should have been deleted page.should_not have_field 'product_product_properties_attributes_0_property_name', with: 'fooprop' page.should_not have_field 'product_product_properties_attributes_0_value', with: 'fooval' + expect(p.reload.property('fooprop')).to be_nil end diff --git a/spec/helpers/navigation_helper_spec.rb b/spec/helpers/navigation_helper_spec.rb index 76fe9573f2..e90d46cd57 100644 --- a/spec/helpers/navigation_helper_spec.rb +++ b/spec/helpers/navigation_helper_spec.rb @@ -3,23 +3,23 @@ require 'spec_helper' module Spree module Admin describe NavigationHelper do - describe "klass_for" do - it "returns the class when present" do - helper.klass_for('products').should == Spree::Product - end + # describe "klass_for" do + # it "returns the class when present" do + # helper.klass_for('products').should == Spree::Product + # end - it "returns a symbol when there's no available class" do - helper.klass_for('reports').should == :report - end + # it "returns a symbol when there's no available class" do + # helper.klass_for('reports').should == :report + # end - it "returns :overview for the dashboard" do - helper.klass_for('dashboard').should == :overview - end + # it "returns :overview for the dashboard" do + # helper.klass_for('dashboard').should == :overview + # end - it "returns Spree::Order for bulk_order_management" do - helper.klass_for('bulk_order_management').should == Spree::Order - end - end + # it "returns Spree::Order for bulk_order_management" do + # helper.klass_for('bulk_order_management').should == Spree::Order + # end + # end end end end diff --git a/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee b/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee index 702ef2cc1c..5c81f72d97 100644 --- a/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee +++ b/spec/javascripts/unit/admin/enterprises/services/enterprises_spec.js.coffee @@ -37,25 +37,14 @@ describe "Enterprises service", -> expect(result).toDeepEqual response describe "when params are passed", -> - describe "where includeBlank param is truthy", -> - beforeEach -> - params = {includeBlank: true, someParam: 'someVal'} - $httpBackend.expectGET('/admin/enterprises.json?someParam=someVal').respond 200, response - result = Enterprises.index(params) - $httpBackend.flush() + beforeEach -> + params = { someParam: 'someVal'} + $httpBackend.expectGET('/admin/enterprises.json?someParam=someVal').respond 200, response + result = Enterprises.index(params) + $httpBackend.flush() - it "returns an array of enterprises, with a blank option appended to the beginning", -> - expect(result).toDeepEqual [{id: '0', name: 'All'} ,{ id: 5, name: 'Enterprise 1'}] - - describe "where includeBlank param is falsey", -> - beforeEach -> - params = {includeBlank: false, someParam: 'someVal'} - $httpBackend.expectGET('/admin/enterprises.json?someParam=someVal').respond 200, response - result = Enterprises.index(params) - $httpBackend.flush() - - it "returns an array of enterprises, with a blank option appended to the beginning", -> - expect(result).toDeepEqual response + it "returns an array of enterprises", -> + expect(result).toDeepEqual response describe "#save", -> diff --git a/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee b/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee index a1c291f5b0..665d41934a 100644 --- a/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/line_items/controllers/line_items_controller_spec.js.coffee @@ -63,17 +63,17 @@ describe "LineItemsCtrl", -> $timeout.flush() describe "initialisation", -> - it "gets suppliers, adds a blank option as the first in the list", -> - expect(scope.suppliers).toDeepEqual [ { id : '0', name : 'All' }, supplier ] + it "gets suppliers", -> + expect(scope.suppliers).toDeepEqual [supplier ] - it "gets distributors, adds a blank option as the first in the list", -> - expect(scope.distributors).toDeepEqual [ { id : '0', name : 'All' }, distributor ] + it "gets distributors", -> + expect(scope.distributors).toDeepEqual [ distributor ] it "stores enterprises in an list that is accessible by id", -> expect(Enterprises.enterprisesByID[1]).toDeepEqual supplier - it "gets order cycles, adds a blank option as the first in the list", -> - expect(scope.orderCycles).toDeepEqual [ { id : '0', name : 'All' }, orderCycle ] + it "gets order cycles", -> + expect(scope.orderCycles).toDeepEqual [ orderCycle ] it "gets orders, with dereferenced order cycles and distributors", -> expect(scope.orders).toDeepEqual [ { id: 9, order_cycle: orderCycle, distributor: distributor, number: "R123456" } ] @@ -85,9 +85,9 @@ describe "LineItemsCtrl", -> expect(scope.RequestMonitor.loading).toBe false it "resets the select filters", -> - expect(scope.distributorFilter).toBe '0' - expect(scope.supplierFilter).toBe '0' - expect(scope.orderCycleFilter).toBe '0' + expect(scope.distributorFilter).toBe 0 + expect(scope.supplierFilter).toBe 0 + expect(scope.orderCycleFilter).toBe 0 expect(scope.quickSearch).toBe = "" it "resets the form state to pristine", -> diff --git a/spec/javascripts/unit/darkswarm/filters/localize_currency_spec.js.coffee b/spec/javascripts/unit/darkswarm/filters/localize_currency_spec.js.coffee index 0d21c7de6c..2a690ed0a7 100644 --- a/spec/javascripts/unit/darkswarm/filters/localize_currency_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/filters/localize_currency_spec.js.coffee @@ -7,9 +7,6 @@ describe 'convert number to localised currency ', -> symbol_position: "before" currency: "D" hide_cents: "false" - # Not used yet... - # decimal_mark: "." - # thousands_separator: "," module 'Darkswarm' module ($provide)-> $provide.value "currencyConfig", currencyconfig @@ -38,5 +35,3 @@ describe 'convert number to localised currency ', -> it "can hide cents", -> currencyconfig.hide_cents = "true" expect(filter(5)).toEqual "$5" - - diff --git a/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb b/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb index 9ad1d222b3..b1a9074efb 100644 --- a/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb +++ b/spec/lib/open_food_network/enterprise_fee_applicator_spec.rb @@ -1,3 +1,4 @@ +require 'spec_helper' require 'open_food_network/enterprise_fee_applicator' module OpenFoodNetwork diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 44321353fe..0057d377e7 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -149,13 +149,13 @@ module Spree it "should be able to read/write their enterprises' products and variants" do should have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p1) - should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p1.master) + should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy, :delete], for: p1.master) end it "should be able to read/write related enterprises' products and variants with manage_products permission" do er_ps should have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p_related) - should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p_related.master) + should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy, :delete], for: p_related.master) end it "should not be able to read/write other enterprises' products and variants" do @@ -173,7 +173,7 @@ module Spree it "should be able to read/write their enterprises' product variants" do should have_ability([:create], for: Spree::Variant) - should have_ability([:admin, :index, :read, :create, :edit, :search, :update, :destroy], for: p1.master) + should have_ability([:admin, :index, :read, :create, :edit, :search, :update, :destroy, :delete], for: p1.master) end it "should not be able to read/write other enterprises' product variants" do diff --git a/spec/models/spree/calculator/flat_percent_item_total_spec.rb b/spec/models/spree/calculator/flat_percent_item_total_spec.rb new file mode 100644 index 0000000000..02b6e5d1ae --- /dev/null +++ b/spec/models/spree/calculator/flat_percent_item_total_spec.rb @@ -0,0 +1,10 @@ + describe Spree::Calculator::FlatPercentItemTotal do + let(:calculator) { Spree::Calculator::FlatPercentItemTotal.new } + let(:line_item) { mock_model(Spree::LineItem, amount: 10) } + + before { calculator.stub :preferred_flat_percent => 10 } + + it "should compute amount correctly for a single line item" do + calculator.compute(line_item).should == 1.0 + end +end diff --git a/spec/models/spree/calculator/flexi_rate_spec.rb b/spec/models/spree/calculator/flexi_rate_spec.rb new file mode 100644 index 0000000000..a242429dca --- /dev/null +++ b/spec/models/spree/calculator/flexi_rate_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Spree::Calculator::FlexiRate do + let(:calculator) { Spree::Calculator::FlexiRate.new } + let(:line_item) { mock_model(Spree::LineItem, amount: 10, quantity: 4) } + + describe "computing for a single line item" do + it "returns the first item rate" do + calculator.stub preferred_first_item: 1.0 + calculator.compute(line_item).round(2).should == 1.0 + end + end + + it "allows creation of new object with all the attributes" do + Spree::Calculator::FlexiRate.new(preferred_first_item: 1, preferred_additional_item: 1, preferred_max_items: 1) + end +end diff --git a/spec/models/spree/calculator/per_item_spec.rb b/spec/models/spree/calculator/per_item_spec.rb new file mode 100644 index 0000000000..09c2fb02f6 --- /dev/null +++ b/spec/models/spree/calculator/per_item_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe Spree::Calculator::PerItem do + let(:calculator) { Spree::Calculator::PerItem.new(preferred_amount: 10) } + let(:shipping_calculable) { double(:calculable) } + let(:line_item) { double(:line_item, quantity: 5, product: double(:product)) } + + it "correctly calculates on a single line item object" do + calculator.stub(calculable: shipping_calculable) + calculator.compute(line_item).to_f.should == 50 # 5 x 10 + end +end diff --git a/spec/models/spree/calculator/price_sack_spec.rb b/spec/models/spree/calculator/price_sack_spec.rb new file mode 100644 index 0000000000..b34771c720 --- /dev/null +++ b/spec/models/spree/calculator/price_sack_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Spree::Calculator::PriceSack do + let(:calculator) do + calculator = Spree::Calculator::PriceSack.new + calculator.preferred_minimal_amount = 5 + calculator.preferred_normal_amount = 10 + calculator.preferred_discount_amount = 1 + calculator + end + + let(:line_item) { stub_model(Spree::LineItem, price: 1, quantity: 2) } + + it "computes with a line item object" do + calculator.compute(line_item) + end +end diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index 10e67e5900..2e188244a9 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -585,10 +585,10 @@ module Spree describe "finding products in stock for a particular distribution" do it "returns on-demand products" do p = create(:simple_product, on_demand: true) - p.master.update_attribute(:count_on_hand, 0) + p.variants.first.update_attributes!(count_on_hand: 0, on_demand: true) d = create(:distributor_enterprise) oc = create(:simple_order_cycle, distributors: [d]) - oc.exchanges.outgoing.first.variants << p.master + oc.exchanges.outgoing.first.variants << p.variants.first p.should have_stock_for_distribution(oc, d) end diff --git a/spec/support/request/web_helper.rb b/spec/support/request/web_helper.rb index 23f9757c5b..bca12c46ab 100644 --- a/spec/support/request/web_helper.rb +++ b/spec/support/request/web_helper.rb @@ -78,7 +78,7 @@ module WebHelper end def flash_message - find('.flash').text.strip + find('.flash', visible: false).text.strip end def errors