diff --git a/.rubocop_styleguide.yml b/.rubocop_styleguide.yml
index ddf8e236b8..790240470b 100644
--- a/.rubocop_styleguide.yml
+++ b/.rubocop_styleguide.yml
@@ -186,6 +186,9 @@ Lint/AssignmentInCondition:
Metrics/AbcSize:
Max: 15
+Metrics/BlockLength:
+ ExcludedMethods: ["describe", "context"]
+
Metrics/BlockNesting:
Max: 3
diff --git a/Gemfile b/Gemfile
index 0e88665db5..ffad5d6a8d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -154,4 +154,6 @@ group :development do
# While we don't require this gem directly, no dependents forced the upgrade to a version
# greater than 1.0.9, so we just required the latest available version here.
gem 'eventmachine', '>= 1.2.3'
+
+ gem 'rack-mini-profiler', '< 1.0.0'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 8716b74277..c0914e10d1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -578,6 +578,8 @@ GEM
rack (1.4.7)
rack-cache (1.8.0)
rack (>= 0.4)
+ rack-mini-profiler (0.10.7)
+ rack (>= 1.2.0)
rack-rewrite (1.5.1)
rack-ssl (1.3.4)
rack
@@ -683,7 +685,7 @@ GEM
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
- skylight (1.6.1)
+ skylight (1.7.1)
activesupport (>= 3.0.0)
spinjs-rails (1.3)
rails (>= 3.1)
@@ -716,7 +718,7 @@ GEM
unicorn (5.4.1)
kgio (~> 2.6)
raindrops (~> 0.7)
- unicorn-rails (1.1.0)
+ unicorn-rails (2.2.1)
rack
unicorn
uuidtools (2.1.5)
@@ -809,6 +811,7 @@ DEPENDENCIES
poltergeist (>= 1.16.0)
pry-byebug (>= 3.4.3)
rabl
+ rack-mini-profiler (< 1.0.0)
rack-rewrite
rack-ssl
rails (~> 3.2.22)
diff --git a/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee b/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee
index c5936393db..ba37f0518f 100644
--- a/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee
+++ b/app/assets/javascripts/admin/enterprise_fees/directives/delete_resource.js.coffee
@@ -1,7 +1,7 @@
angular.module('admin.enterpriseFees').directive 'spreeDeleteResource', ->
(scope, element, attrs) ->
if scope.enterprise_fee.id
- url = '/admin/enterprise_fees/' + scope.enterprise_fee.id
+ url = '/api/enterprise_fees/' + scope.enterprise_fee.id
html = ''
#var html = '
Delete';
element.append html
diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee
index e85f9e5cee..d61ff6ceb7 100644
--- a/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee
+++ b/app/assets/javascripts/darkswarm/controllers/checkout/accordion_controller.js.coffee
@@ -1,25 +1,22 @@
Darkswarm.controller "AccordionCtrl", ($scope, localStorageService, $timeout, $document, CurrentHub) ->
- key = "accordion_#{$scope.order.id}#{CurrentHub.hub.id}#{$scope.order.user_id}"
- value = if localStorageService.get(key) then {} else { details: true, billing: false, shipping: false, payment: false }
- localStorageService.bind $scope, "accordion", value, key
$scope.accordionSections = ["details", "billing", "shipping", "payment"]
- # Scrolling is confused by our position:fixed top bar - add an offset to scroll
- # to the correct location, plus 5px buffer
- offset_height = $("nav.top-bar").height() + 5
+ $scope.accordion = { details: true, billing: true, shipping: true, payment: true }
- $scope.show = (section)->
+ $scope.show = (section) ->
$scope.accordion[section] = true
- # If we call scrollTo() directly after show(), when one of the accordions above the
- # scroll location is closed by show(), scrollTo() will scroll to the old location of
- # the element. Putting this in a 50 ms timeout is enough delay for the DOM to
- # have updated.
- $timeout ->
- $document.scrollTo($("##{section}"), offset_height, 500)
- , 50
+
+ $scope.scrollTo = (section) ->
+ # Scrolling is confused by our position:fixed top bar - add an offset to scroll
+ # to the correct location, plus 5px buffer
+ offset_height = $("nav.top-bar").height() + 5
+ $document.scrollTo($("##{section}"), offset_height, 400)
$scope.$on 'purchaseFormInvalid', (event, form) ->
# Scroll to first invalid section
for section in $scope.accordionSections
if not form[section].$valid
$scope.show section
+ $timeout ->
+ $scope.scrollTo(section)
+ , 50
break
diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee
index b8dec8b190..b7246fddd9 100644
--- a/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee
+++ b/app/assets/javascripts/darkswarm/controllers/checkout/billing_controller.js.coffee
@@ -5,7 +5,7 @@ Darkswarm.controller "BillingCtrl", ($scope, $timeout) ->
$scope.summary = ->
[$scope.order.bill_address.address1,
- $scope.order.bill_address.city,
+ $scope.order.bill_address.city,
$scope.order.bill_address.zipcode]
- $timeout $scope.onTimeout
+ $timeout $scope.onTimeout
diff --git a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee
index e8a6b1ff23..30c243ed7c 100644
--- a/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee
+++ b/app/assets/javascripts/darkswarm/controllers/checkout/details_controller.js.coffee
@@ -13,11 +13,11 @@ Darkswarm.controller "DetailsCtrl", ($scope, $timeout, $http, CurrentUser, Authe
$scope.summary = ->
[$scope.fullName(),
- $scope.order.email,
+ $scope.order.email,
$scope.order.bill_address.phone]
$scope.fullName = ->
- [$scope.order.bill_address.firstname ? null,
+ [$scope.order.bill_address.firstname ? null,
$scope.order.bill_address.lastname ? null].join(" ").trim()
- $timeout $scope.onTimeout
+ $timeout $scope.onTimeout
diff --git a/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee b/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee
index 739d2de9bd..d8bb1b262e 100644
--- a/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee
+++ b/app/assets/javascripts/darkswarm/mixins/fieldset_mixin.js.coffee
@@ -2,11 +2,11 @@ window.FieldsetMixin = ($scope)->
$scope.next = (event = false)->
event.preventDefault() if event
return unless $scope.nextPanel
+ $scope.accordion[$scope.name] = false
$scope.show $scope.nextPanel
$scope.onTimeout = ->
- if $scope[$scope.name].$valid
- $scope.next()
+ $scope.accordion[$scope.name] = !$scope[$scope.name].$valid
$scope.valid = ->
$scope.form().$valid
diff --git a/app/controllers/admin/enterprise_fees_controller.rb b/app/controllers/admin/enterprise_fees_controller.rb
index 528284c4e4..46e2b535fb 100644
--- a/app/controllers/admin/enterprise_fees_controller.rb
+++ b/app/controllers/admin/enterprise_fees_controller.rb
@@ -2,7 +2,6 @@ module Admin
class EnterpriseFeesController < ResourceController
before_filter :load_enterprise_fee_set, :only => :index
before_filter :load_data
- before_filter :do_not_destroy_referenced_fees, :only => :destroy
def index
@@ -45,22 +44,6 @@ module Admin
private
- def do_not_destroy_referenced_fees
- product_distribution = ProductDistribution.where(:enterprise_fee_id => @object).first
- if product_distribution
- p = product_distribution.product
- error = I18n.t(:enterprise_fees_destroy_error, id: p.id, name: p.name)
-
- respond_with(@object) do |format|
- format.html do
- flash[:error] = error
- redirect_to collection_url
- end
- format.js { render text: error, status: 403 }
- end
- end
- end
-
def load_enterprise_fee_set
@enterprise_fee_set = EnterpriseFeeSet.new :collection => collection
end
diff --git a/app/controllers/api/enterprise_fees_controller.rb b/app/controllers/api/enterprise_fees_controller.rb
new file mode 100644
index 0000000000..3d03b28515
--- /dev/null
+++ b/app/controllers/api/enterprise_fees_controller.rb
@@ -0,0 +1,21 @@
+module Api
+ class EnterpriseFeesController < BaseController
+ respond_to :json
+
+ def destroy
+ authorize! :destroy, enterprise_fee
+
+ if enterprise_fee.destroy
+ render text: I18n.t(:successfully_removed), status: 204
+ else
+ render text: enterprise_fee.errors.full_messages.first, status: 403
+ end
+ end
+
+ private
+
+ def enterprise_fee
+ @enterprise_fee ||= EnterpriseFee.find_by_id params[:id]
+ end
+ end
+end
diff --git a/app/helpers/enterprises_helper.rb b/app/helpers/enterprises_helper.rb
index 8cef0281b1..e1b85fc14b 100644
--- a/app/helpers/enterprises_helper.rb
+++ b/app/helpers/enterprises_helper.rb
@@ -55,7 +55,7 @@ module EnterprisesHelper
if enterprise.sells == 'none'
enterprise.producer_profile_only ? I18n.t(:profile) : I18n.t(:supplier_only)
else
- "Has Shopfront"
+ I18n.t(:has_shopfront)
end
end
diff --git a/app/models/enterprise_fee.rb b/app/models/enterprise_fee.rb
index 05276cf3d7..60c8bb9726 100644
--- a/app/models/enterprise_fee.rb
+++ b/app/models/enterprise_fee.rb
@@ -26,6 +26,7 @@ class EnterpriseFee < ActiveRecord::Base
validates_presence_of :name
before_save :ensure_valid_tax_category_settings
+ before_destroy :ensure_no_product_distributions
scope :for_enterprise, lambda { |enterprise| where(enterprise_id: enterprise) }
scope :for_enterprises, lambda { |enterprises| where(enterprise_id: enterprises) }
@@ -68,6 +69,15 @@ class EnterpriseFee < ActiveRecord::Base
return true
end
+ def ensure_no_product_distributions
+ dependent_distribution = ProductDistribution.where(enterprise_fee_id: self).first
+ return unless dependent_distribution
+ product = dependent_distribution.product
+ error = I18n.t(:enterprise_fees_destroy_error, id: product.id, name: product.name)
+ errors.add(:base, error)
+ false
+ end
+
def refresh_products_cache
OpenFoodNetwork::ProductsCache.enterprise_fee_changed self
end
diff --git a/app/models/product_import/product_importer.rb b/app/models/product_import/product_importer.rb
index 3bc66fa815..3b8671290f 100644
--- a/app/models/product_import/product_importer.rb
+++ b/app/models/product_import/product_importer.rb
@@ -100,7 +100,8 @@ module ProductImport
entries[entry.line_number] = {
attributes: entry.displayable_attributes,
validates_as: entry.validates_as,
- errors: entry.invalid_attributes
+ errors: entry.invalid_attributes,
+ product_validations: entry.product_validations
}
end
entries.to_json
diff --git a/app/overrides/spree/admin/orders/_form/add_distribution_fields.html.haml.deface b/app/overrides/spree/admin/orders/_form/add_distribution_fields.html.haml.deface
deleted file mode 100644
index af07be1d23..0000000000
--- a/app/overrides/spree/admin/orders/_form/add_distribution_fields.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ insert_before "[data-hook='admin_order_form_buttons']"
-
-= render partial: 'spree/admin/orders/_form/distribution_fields'
diff --git a/app/overrides/spree/admin/orders/_form/hide_form_until_distribution.deface b/app/overrides/spree/admin/orders/_form/hide_form_until_distribution.deface
deleted file mode 100644
index 7fe5652aae..0000000000
--- a/app/overrides/spree/admin/orders/_form/hide_form_until_distribution.deface
+++ /dev/null
@@ -1,2 +0,0 @@
-add_to_attributes "table.index, [data-hook='admin_order_form_buttons']"
-attributes "ng-show" => "distributionChosen()"
diff --git a/app/overrides/spree/admin/orders/_form/relabel_update_button.html.haml.deface b/app/overrides/spree/admin/orders/_form/relabel_update_button.html.haml.deface
deleted file mode 100644
index d4d3aefc8d..0000000000
--- a/app/overrides/spree/admin/orders/_form/relabel_update_button.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ replace "code[erb-loud]:contains('button t(:update)')"
-
-= button t(:update_and_recalculate_fees), 'icon-refresh'
diff --git a/app/overrides/spree/admin/orders/_line_item/replace_variant_label.html.haml.deface b/app/overrides/spree/admin/orders/_line_item/replace_variant_label.html.haml.deface
deleted file mode 100644
index 6481791112..0000000000
--- a/app/overrides/spree/admin/orders/_line_item/replace_variant_label.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ replace 'code[erb-loud]:contains(\'"(#{f.object.variant.options_text})"\')'
-
-= "(#{f.object.full_name})"
diff --git a/app/overrides/spree/admin/orders/_line_item/replace_variant_price.html.haml.deface b/app/overrides/spree/admin/orders/_line_item/replace_variant_price.html.haml.deface
deleted file mode 100644
index 605f645996..0000000000
--- a/app/overrides/spree/admin/orders/_line_item/replace_variant_price.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ replace 'code[erb-loud]:contains(\'f.object.variant.display_amount\')'
-
-= f.object.single_money
diff --git a/app/overrides/spree/admin/orders/edit/add_action_dropdown.html.haml.deface b/app/overrides/spree/admin/orders/edit/add_action_dropdown.html.haml.deface
deleted file mode 100644
index 58b13a3b32..0000000000
--- a/app/overrides/spree/admin/orders/edit/add_action_dropdown.html.haml.deface
+++ /dev/null
@@ -1,6 +0,0 @@
-/ insert_after "code[erb-loud]:contains('button_link_to t(:resend)')"
-
-%li.links-dropdown#links-dropdown{ links: order_links(@order).to_json }
-
-:coffee
- angular.bootstrap(document.getElementById("links-dropdown"),['admin.dropdown'])
diff --git a/app/overrides/spree/admin/orders/edit/suppress_errors.html.haml.deface b/app/overrides/spree/admin/orders/edit/suppress_errors.html.haml.deface
deleted file mode 100644
index 31a8c961e8..0000000000
--- a/app/overrides/spree/admin/orders/edit/suppress_errors.html.haml.deface
+++ /dev/null
@@ -1,6 +0,0 @@
-/ replace "code[erb-loud]:contains(\'error_messages\')"
-
--# Suppress errors when manually creating a new order - needs to proceed to edit page
--# without having line items (which otherwise gives a validation error)
-- unless params["suppress_error_msg"]
- = render partial: "spree/shared/error_messages", :locals => { :target => @order }
diff --git a/app/overrides/spree/admin/products/_form/add_description_wysiwyg.html.haml.deface b/app/overrides/spree/admin/products/_form/add_description_wysiwyg.html.haml.deface
deleted file mode 100644
index d04e787482..0000000000
--- a/app/overrides/spree/admin/products/_form/add_description_wysiwyg.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ replace "[data-hook=admin_product_form_left] code[erb-loud]:contains('f.text_area :description')"
-%text-angular{'id' => 'product_description', 'name' => 'product[description]', 'class' => 'text-angular', 'textangular-strip' => true, 'ta-paste' => "stripFormatting($html)", 'ta-toolbar' => "[['bold','italics','clear']]"}
- = sanitize(@product.description)
diff --git a/app/overrides/spree/admin/products/_form/add_primary_taxon_field.html.haml.deface b/app/overrides/spree/admin/products/_form/add_primary_taxon_field.html.haml.deface
deleted file mode 100644
index 46afe1f94d..0000000000
--- a/app/overrides/spree/admin/products/_form/add_primary_taxon_field.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ insert_after "div[class='variant_units_form']"
-
-= render 'spree/admin/products/primary_taxon_form', f: f
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/add_supplier.html.haml.deface b/app/overrides/spree/admin/products/_form/add_supplier.html.haml.deface
deleted file mode 100644
index a814c10b80..0000000000
--- a/app/overrides/spree/admin/products/_form/add_supplier.html.haml.deface
+++ /dev/null
@@ -1,6 +0,0 @@
-/ insert_before "code[erb-loud]:contains('f.field_container :price')"
-= f.field_container :supplier do
- = f.label :supplier, t(:spree_admin_supplier)
- %br
- = f.collection_select(:supplier_id, @producers, :id, :name, {:include_blank => true}, {:class => "select2"})
- = f.error_message_on :supplier
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/add_units_form.html.haml.deface b/app/overrides/spree/admin/products/_form/add_units_form.html.haml.deface
deleted file mode 100644
index 6571fb3ab6..0000000000
--- a/app/overrides/spree/admin/products/_form/add_units_form.html.haml.deface
+++ /dev/null
@@ -1,17 +0,0 @@
-/ insert_top "[data-hook='admin_product_form_right']"
-
-.variant_units_form{ 'ng-app' => 'admin.products', 'ng-controller' => 'editUnitsCtrl' }
-
- = f.field_container :units do
- = f.label :variant_unit_with_scale, t(:spree_admin_variant_unit_scale)
- %select.select2.fullwidth{ id: 'product_variant_unit_with_scale', 'ng-model' => 'variant_unit_with_scale', 'ng-change' => 'setFields()', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options' }
- %option{'value' => ''}
-
- = f.text_field :variant_unit, {'id' => 'variant_unit', 'ng-value' => 'product.variant_unit', 'hidden' => true}
- = f.text_field :variant_unit_scale, {'id' => 'variant_unit_scale', 'ng-value' => 'product.variant_unit_scale', 'hidden' => true}
-
- .variant_unit_name{'ng-show' => 'product.variant_unit == "items"'}
- = f.field_container :variant_unit_name do
- = f.label :variant_unit_name, t(:spree_admin_variant_unit_name)
- = f.text_field :variant_unit_name, {placeholder: t('admin.products.unit_name_placeholder')}
- = f.error_message_on :variant_unit_name
diff --git a/app/overrides/spree/admin/products/_form/remove_available_on.deface b/app/overrides/spree/admin/products/_form/remove_available_on.deface
deleted file mode 100644
index 645fb76bde..0000000000
--- a/app/overrides/spree/admin/products/_form/remove_available_on.deface
+++ /dev/null
@@ -1,2 +0,0 @@
-remove "code[erb-loud]:contains('f.label :available_on')"
-closing_selector("code[erb-loud]:contains('f.text_field :available_on')")
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/remove_cost_currency.deface b/app/overrides/spree/admin/products/_form/remove_cost_currency.deface
deleted file mode 100644
index a194a5e03a..0000000000
--- a/app/overrides/spree/admin/products/_form/remove_cost_currency.deface
+++ /dev/null
@@ -1,2 +0,0 @@
-remove "code[erb-loud]:contains('f.field_container :cost_currency')"
-closing_selector("code[erb-silent]:contains('end')")
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/remove_cost_price.deface b/app/overrides/spree/admin/products/_form/remove_cost_price.deface
deleted file mode 100644
index 9f9cd8ec3f..0000000000
--- a/app/overrides/spree/admin/products/_form/remove_cost_price.deface
+++ /dev/null
@@ -1,2 +0,0 @@
-remove "code[erb-loud]:contains('f.field_container :cost_price')"
-closing_selector("code[erb-silent]:contains('end')")
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/remove_meta_description.deface b/app/overrides/spree/admin/products/_form/remove_meta_description.deface
deleted file mode 100644
index 15a00a5df0..0000000000
--- a/app/overrides/spree/admin/products/_form/remove_meta_description.deface
+++ /dev/null
@@ -1 +0,0 @@
-remove "div[data-hook='admin_product_form_meta']"
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/remove_option_types_and_taxons.deface b/app/overrides/spree/admin/products/_form/remove_option_types_and_taxons.deface
deleted file mode 100644
index eeccddc25c..0000000000
--- a/app/overrides/spree/admin/products/_form/remove_option_types_and_taxons.deface
+++ /dev/null
@@ -1 +0,0 @@
-remove "div[class='twelve columns alpha omega']"
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/replace_master_price_label.html.haml.deface b/app/overrides/spree/admin/products/_form/replace_master_price_label.html.haml.deface
deleted file mode 100644
index 02152cb521..0000000000
--- a/app/overrides/spree/admin/products/_form/replace_master_price_label.html.haml.deface
+++ /dev/null
@@ -1,2 +0,0 @@
-/ replace "[data-hook=admin_product_form_right] code[erb-loud]:contains('f.label :price')"
-= f.label :price, raw(t(:price) + content_tag(:span, ' *', :class => 'required'))
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/_form/replace_taxons_div.html.haml.deface b/app/overrides/spree/admin/products/_form/replace_taxons_div.html.haml.deface
deleted file mode 100644
index 697255ab70..0000000000
--- a/app/overrides/spree/admin/products/_form/replace_taxons_div.html.haml.deface
+++ /dev/null
@@ -1,5 +0,0 @@
-/ insert_bottom "[data-hook=admin_product_form_left]"
-= f.field_container :taxons do
- = f.label :taxon_ids, t(:taxons)
- %br
- = f.hidden_field :taxon_ids, :value => @product.taxon_ids.join(',')
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/edit/add_angular.deface b/app/overrides/spree/admin/products/edit/add_angular.deface
deleted file mode 100644
index 926c47c0ec..0000000000
--- a/app/overrides/spree/admin/products/edit/add_angular.deface
+++ /dev/null
@@ -1,2 +0,0 @@
-add_to_attributes 'fieldset.no-border-top'
-attributes 'ng-app' => 'admin.products'
\ No newline at end of file
diff --git a/app/overrides/spree/admin/products/edit/nojs_new_product.html.haml.deface b/app/overrides/spree/admin/products/edit/nojs_new_product.html.haml.deface
deleted file mode 100644
index ff1bad39cd..0000000000
--- a/app/overrides/spree/admin/products/edit/nojs_new_product.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ replace_contents "#new_product_link"
-
-= button_link_to t(:new_product), new_object_url, {:icon => 'icon-plus', :id => 'admin_new_product' }
diff --git a/app/overrides/spree/admin/products/edit/return_to_products.html.haml.deface b/app/overrides/spree/admin/products/edit/return_to_products.html.haml.deface
deleted file mode 100644
index 1865179b4c..0000000000
--- a/app/overrides/spree/admin/products/edit/return_to_products.html.haml.deface
+++ /dev/null
@@ -1,3 +0,0 @@
-/ replace "code[erb-loud]:contains('button_link_to t(:back_to_products_list)')"
-
-= button_link_to t('admin.products.back_to_products_list'), admin_products_path, :icon => 'icon-arrow-left'
diff --git a/app/views/admin/product_import/_errors_list.html.haml b/app/views/admin/product_import/_errors_list.html.haml
index 787aabe76b..8397c7013b 100644
--- a/app/views/admin/product_import/_errors_list.html.haml
+++ b/app/views/admin/product_import/_errors_list.html.haml
@@ -7,3 +7,5 @@
( {{entry.attributes.display_name}} )
%p.error{ng: {repeat: "(attribute, error) in entry.errors", show: "ignore_fields.indexOf(attribute) < 0" }}
- {{error}}
+ %p.error{ng: {repeat: "(attribute, error) in entry.product_validations"}}
+ - {{error}}
diff --git a/app/views/checkout/edit.html.haml b/app/views/checkout/edit.html.haml
index 75c9eff08f..ab5253538b 100644
--- a/app/views/checkout/edit.html.haml
+++ b/app/views/checkout/edit.html.haml
@@ -16,7 +16,7 @@
= render partial: "shopping_shared/details"
- %accordion{"close-others" => "true"}
+ %accordion{"close-others" => "false"}
%checkout.row{"ng-controller" => "CheckoutCtrl"}
.small-12.medium-8.large-9.columns
- unless spree_current_user
diff --git a/app/views/spree/admin/orders/_add_product.html.haml b/app/views/spree/admin/orders/_add_product.html.haml
new file mode 100644
index 0000000000..eecc678521
--- /dev/null
+++ b/app/views/spree/admin/orders/_add_product.html.haml
@@ -0,0 +1,17 @@
+= render partial: "spree/admin/variants/autocomplete", formats: :js
+#add-line-item
+ %fieldset
+ %legend{align: "center"}
+ = t(:add_product)
+ .field.eight.columns.alpha
+ = label_tag :add_product_name, t(:name_or_sku)
+ = hidden_field_tag :add_variant_id, "", class: "variant_autocomplete fullwidth"
+ .field.two.columns
+ = label_tag :add_quantity, t(:qty)
+ = number_field_tag :add_quantity, 1, min: 0
+ .actions.two.columns.omega
+ = link_to_with_icon 'icon-plus', t(:add), admin_order_line_items_url(@order),
+ method: :post,
+ id: 'add_line_item_to_order',
+ class: 'button fullwidth',
+ 'data-update' => 'order-form-wrapper'
diff --git a/app/views/spree/admin/orders/_form.html.haml b/app/views/spree/admin/orders/_form.html.haml
new file mode 100644
index 0000000000..8564ae04f5
--- /dev/null
+++ b/app/views/spree/admin/orders/_form.html.haml
@@ -0,0 +1,68 @@
+%div
+ - if @line_item.try(:errors).present?
+ = render partial: 'spree/shared/error_messages', locals: { target: @line_item }
+ = form_for @order, url: admin_order_url(@order), method: :put do |f|
+ %fieldset.no-border-top
+ = f.hidden_field :number
+ %table.index{"ng-show" => "distributionChosen()"}
+ %colgroup
+ %col{style: "width: 49%;"}/
+ %col{style: "width: 14%;"}/
+ %col{style: "width: 10%;"}/
+ %col{style: "width: 14%;"}/
+ %col{style: "width: 8%;"}/
+ %thead#line-items
+ %tr
+ %th
+ = t(:item_description)
+ %th.price
+ = t(:price)
+ %th.qty
+ = t(:qty)
+ %th.total
+ %span
+ = t(:total)
+ %th.orders-actions.actions
+ %tbody
+ = f.fields_for :line_items do |li_form|
+ = render partial: 'spree/admin/orders/line_item', locals: { f: li_form }
+ %tbody#subtotal.no-border-top
+ %tr#subtotal-row
+ %td{colspan: "3"}
+ %b
+ = t(:subtotal)
+ \:
+ %td.total.align-center
+ %span
+ = @order.display_item_total.to_html
+ %td.actions
+ %tbody#order-charges.no-border-top
+ - @order.adjustments.eligible.each do |adjustment|
+ %tr
+ %td{colspan: "3"}
+ %strong
+ = adjustment.label
+ \:
+ %td.total.align-center
+ %span= adjustment.display_amount.to_html
+ %td.actions
+ %tbody#order-total.grand-total.no-border-top
+ %tr
+ %td{colspan: "3"}
+ %b
+ = t(:order_total)
+ \:
+ %td.total.align-center
+ %span#order_total
+ = @order.display_total.to_html
+ %td.actions
+
+ = render partial: 'spree/admin/orders/_form/distribution_fields'
+
+ .filter-actions.actions{"ng-show" => "distributionChosen()"}
+ = button t(:update_and_recalculate_fees), 'icon-refresh'
+ %span.or
+ = t(:or)
+ = link_to_with_icon 'button icon-arrow-left', t(:back), admin_orders_url
+ = javascript_tag do
+ = render partial: 'spree/admin/shared/update_order_state', handlers: [:js]
diff --git a/app/views/spree/admin/orders/_line_item.html.haml b/app/views/spree/admin/orders/_line_item.html.haml
new file mode 100644
index 0000000000..9afed0e2ec
--- /dev/null
+++ b/app/views/spree/admin/orders/_line_item.html.haml
@@ -0,0 +1,12 @@
+%tr{id: "#{spree_dom_id(f.object)}", class: "#{cycle('odd', 'even')}"}
+ %td
+ = f.object.variant.product.name
+ = "(#{f.object.full_name})" unless f.object.variant.option_values.empty?
+ %td.price.align-center
+ = f.object.variant.display_amount
+ %td.qty
+ = f.number_field :quantity, min: 0, class: "qty"
+ %td.total.align-center
+ = f.object.single_money
+ %td.actions
+ = link_to_delete f.object, {url: admin_order_line_item_url(@order.number, f.object), no_text: true}
diff --git a/app/views/spree/admin/orders/edit.html.haml b/app/views/spree/admin/orders/edit.html.haml
index f897065224..015e9234e8 100644
--- a/app/views/spree/admin/orders/edit.html.haml
+++ b/app/views/spree/admin/orders/edit.html.haml
@@ -3,6 +3,8 @@
- content_for :page_actions do
%li= event_links
%li= button_link_to t(:resend), resend_admin_order_url(@order), method: :post, icon: 'icon-email'
+ %li.links-dropdown#links-dropdown{ links: order_links(@order).to_json }
+
%li= button_link_to t(:back_to_orders_list), admin_orders_path, icon: 'icon-arrow-left'
= admin_inject_shops(module: 'admin.orders')
@@ -10,15 +12,19 @@
= render 'spree/admin/shared/order_tabs', current: 'Order Details'
-%div{"data-hook" => "admin_order_edit_header"}
- = render 'spree/shared/error_messages', target: @order
+%div
+ - unless params["suppress_error_msg"]
+ = render partial: "spree/shared/error_messages", :locals => { :target => @order }
%div{"ng-app" => "admin.orders", "ng-controller" => "orderCtrl", "ofn-distributor-id" => @order.distributor_id, "ofn-order-cycle-id" => @order.order_cycle_id}
= render 'add_product'
- %div{"data-hook" => "admin_order_edit_form"}
+ %div
#order-form-wrapper
= render 'form', order: @order
- content_for :head do
= javascript_tag 'var expand_variants = true;'
+
+:coffee
+ angular.bootstrap(document.getElementById("links-dropdown"),['admin.dropdown'])
diff --git a/app/views/spree/admin/products/_form.html.haml b/app/views/spree/admin/products/_form.html.haml
new file mode 100644
index 0000000000..4e97d209cd
--- /dev/null
+++ b/app/views/spree/admin/products/_form.html.haml
@@ -0,0 +1,106 @@
+%div{"data-hook" => "admin_product_form_fields"}
+ .left.eight.columns.alpha
+ = f.field_container :name do
+ = f.label :name, raw(t(:name) + content_tag(:span, ' *', :class => 'required'))
+ = f.text_field :name, :class => 'fullwidth title'
+ = f.error_message_on :name
+
+ = f.field_container :permalink do
+ = f.label :permalink, raw(t(:permalink) + content_tag(:span, ' *', :class => "required"))
+ = f.text_field :permalink, :class => 'fullwidth title'
+ = f.error_message_on :permalink
+
+ = f.field_container :description do
+ = f.label :description, t(:description)
+ %text-angular{'id' => 'product_description', 'name' => 'product[description]', 'class' => 'text-angular', 'textangular-strip' => true, 'ta-paste' => "stripFormatting($html)", 'ta-toolbar' => "[['bold','italics','clear']]"}
+ = sanitize(@product.description)
+ = f.error_message_on :description
+
+ = f.field_container :taxons do
+ = f.label :taxon_ids, t(:taxons)
+ %br
+ = f.hidden_field :taxon_ids, :value => @product.taxon_ids.join(',')
+
+ .right.four.columns.omega
+ .variant_units_form{ 'ng-app' => 'admin.products', 'ng-controller' => 'editUnitsCtrl' }
+
+ = f.field_container :units do
+ = f.label :variant_unit_with_scale, t(:spree_admin_variant_unit_scale)
+ %select.select2.fullwidth{ id: 'product_variant_unit_with_scale', 'ng-model' => 'variant_unit_with_scale', 'ng-change' => 'setFields()', 'ng-options' => 'unit[1] as unit[0] for unit in variant_unit_options' }
+ %option{'value' => ''}
+
+ = f.text_field :variant_unit, {'id' => 'variant_unit', 'ng-value' => 'product.variant_unit', 'hidden' => true}
+ = f.text_field :variant_unit_scale, {'id' => 'variant_unit_scale', 'ng-value' => 'product.variant_unit_scale', 'hidden' => true}
+
+ .variant_unit_name{'ng-show' => 'product.variant_unit == "items"'}
+ = f.field_container :variant_unit_name do
+ = f.label :variant_unit_name, t(:spree_admin_variant_unit_name)
+ = f.text_field :variant_unit_name, {placeholder: t('admin.products.unit_name_placeholder')}
+ = f.error_message_on :variant_unit_name
+
+ = render 'spree/admin/products/primary_taxon_form', f: f
+
+ = f.field_container :supplier do
+ = f.label :supplier, t(:spree_admin_supplier)
+ %br
+ = f.collection_select(:supplier_id, @producers, :id, :name, {:include_blank => true}, {:class => "select2"})
+ = f.error_message_on :supplier
+
+ = f.field_container :price do
+ = f.label :price, raw(t(:price) + content_tag(:span, ' *', :class => 'required'))
+ = f.text_field :price, :value => number_to_currency(@product.price, :unit => '')
+ = f.error_message_on :price
+
+ .clear
+
+ - unless @product.has_variants?
+ = f.field_container :sku do
+ = f.label :sku, t(:sku)
+ = f.text_field :sku, :size => 16
+
+ - if Spree::Config[:track_inventory_levels]
+ .alpha.two.columns
+ = f.field_container :on_hand do
+ = f.label :on_hand, t(:on_hand)
+ = f.number_field :on_hand, :min => 0
+ .omega.two.columns
+ = f.field_container :on_demand, :class => ['checkbox'] do
+ %label
+ = f.check_box :on_demand
+ = t(:on_demand)
+
+ .clear
+
+ %ul#shipping_specs
+ %li#shipping_specs_weight_field.field.alpha.two.columns
+ = f.label :weight, t(:weight)
+ = f.text_field :weight, :size => 4
+ %li#shipping_specs_height_field.field.omega.two.columns
+ = f.label :height, t(:height)
+ = f.text_field :height, :size => 4
+ %li#shipping_specs_width_field.field.alpha.two.columns
+ = f.label :width, t(:width)
+ = f.text_field :width, :size => 4
+ %li#shipping_specs_depth_field.field.omega.two.columns
+ = f.label :depth, t(:depth)
+ = f.text_field :depth, :size => 4
+
+ = f.field_container :shipping_categories do
+ = f.label :shipping_category_id, t(:shipping_categories)
+ = f.collection_select(:shipping_category_id, @shipping_categories, :id, :name, { :include_blank => 'None' }, { :class => 'select2' })
+ = f.error_message_on :shipping_category
+
+ = f.field_container :tax_category do
+ = f.label :tax_category_id, t(:tax_category)
+ = f.collection_select(:tax_category_id, @tax_categories, :id, :name, { :include_blank => 'None' }, { :class => 'select2' })
+ = f.error_message_on :tax_category
+
+ .clear
+
+ %div
+
+ .clear
+
+- unless Rails.env.test?
+ :javascript
+ $('.select2-container').css({width: '20em'})
diff --git a/app/views/spree/admin/products/edit.html.haml b/app/views/spree/admin/products/edit.html.haml
new file mode 100644
index 0000000000..95ef4c061c
--- /dev/null
+++ b/app/views/spree/admin/products/edit.html.haml
@@ -0,0 +1,14 @@
+- content_for :page_actions do
+ %li= button_link_to t('admin.products.back_to_products_list'), admin_products_path, :icon => 'icon-arrow-left'
+ %li#new_product_link
+ = button_link_to t(:new_product), new_object_url, { :icon => 'icon-plus', :id => 'admin_new_product' }
+
+= render :partial => 'spree/admin/shared/product_sub_menu'
+
+= render :partial => 'spree/admin/shared/product_tabs', :locals => { :current => 'Product Details' }
+= render :partial => 'spree/shared/error_messages', :locals => { :target => @product }
+
+= form_for [:admin, @product], :method => :put, :html => { :multipart => true } do |f|
+ %fieldset.no-border-top{'ng-app' => 'admin.products'}
+ = render :partial => 'form', :locals => { :f => f }
+ = render :partial => 'spree/admin/shared/edit_resource_links'
diff --git a/app/views/spree/admin/shared/_order_tabs.html.haml b/app/views/spree/admin/shared/_order_tabs.html.haml
new file mode 100644
index 0000000000..d250507193
--- /dev/null
+++ b/app/views/spree/admin/shared/_order_tabs.html.haml
@@ -0,0 +1,75 @@
+- content_for :page_title do
+ = t(:order)
+ \#
+ = @order.number
+
+- if @order.bill_address.present?
+ = @order.bill_address.firstname
+ = @order.bill_address.lastname
+ \-
+
+- content_for :sidebar_title do
+ = t(:order_information)
+
+- content_for :sidebar do
+ %header#order_tab_summary
+ %dl.additional-info
+ %dt#order_status
+ = t(:status)
+ %dd
+ - order_state_classes = "state #{@order.state}"
+ %span{ class: order_state_classes }
+ = t(@order.state, scope: :order_state)
+ %dt
+ = t(:total)
+ \:
+ %dd#order_total
+ = @order.display_total.to_html
+
+ - if @order.completed?
+ %dt
+ = t(:shipment)
+ \:
+ %dd#shipment_status
+ - shipment_state_classes = "state #{@order.shipment_state}"
+ %span{ class: shipment_state_classes }
+ = t(@order.shipment_state, scope: :shipment_states, default: [:missing, "none"])
+ %dt
+ = t(:payment)
+ \:
+ %dd#payment_status
+ - payment_state_classes = "state #{@order.payment_state}"
+ %span{ class: payment_state_classes }
+ = t(@order.payment_state, scope: :payment_states, default: [:missing, "none"])
+ %dt
+ = t(:date_completed)
+ \:
+ %dd#date_complete
+ = pretty_time(@order.completed_at)
+
+ %nav.menu
+ %ul
+ - order_details_classes = "active" if current == "Order Details"
+ %li{ class: order_details_classes }
+ = link_to_with_icon 'icon-edit', t(:order_details), edit_admin_order_url(@order)
+
+ - customer_details_classes = "active" if current == "Customer Details"
+ %li{ class: customer_details_classes }
+ = link_to_with_icon 'icon-user', t(:customer_details), admin_order_customer_url(@order)
+
+ - adjustments_classes = "active" if current == "Adjustments"
+ %li{ class: adjustments_classes }
+ = link_to_with_icon 'icon-cogs', t(:adjustments), admin_order_adjustments_url(@order)
+
+ - payments_classes = "active" if current == "Payments"
+ %li{ class: payments_classes }
+ = link_to_with_icon 'icon-credit-card', t(:payments), admin_order_payments_url(@order)
+
+ - shipments_classes = "active" if current == "Shipments"
+ %li{ class: shipments_classes }
+ = link_to_with_icon 'icon-road', t(:shipments), admin_order_shipments_url(@order)
+
+ - if @order.completed?
+ - authorizations_classes = "active" if current == "Return Authorizations"
+ %li{ class: authorizations_classes }
+ = link_to_with_icon 'icon-share-alt', t(:return_authorizations), admin_order_return_authorizations_url(@order)
diff --git a/app/views/spree/admin/users/_form.html.haml b/app/views/spree/admin/users/_form.html.haml
index e495f29632..47bf167151 100644
--- a/app/views/spree/admin/users/_form.html.haml
+++ b/app/views/spree/admin/users/_form.html.haml
@@ -1,11 +1,11 @@
.row
.alpha.five.columns
= f.field_container :email do
- = f.label :email, Spree.t(:email)
+ = f.label :email, t(".email")
= f.email_field :email, class: "fullwidth"
= error_message_on :user, :email
.field
- = label_tag nil, Spree.t(:roles)
+ = label_tag nil, t(".roles")
%ul
- @roles.each do |role|
%li
@@ -13,14 +13,14 @@
= label_tag role.name
= hidden_field_tag "user[spree_role_ids][]", ""
= f.field_container :enterprise_limit do
- = f.label :enterprise_limit, t(:enterprise_limit)
+ = f.label :enterprise_limit, t(".enterprise_limit")
= f.text_field :enterprise_limit, class: "fullwidth"
.omega.five.columns
= f.field_container :password do
- = f.label :password, Spree.t(:password)
+ = f.label :password, t(".password")
= f.password_field :password, class: "fullwidth"
= f.error_message_on :password
= f.field_container :password do
- = f.label :password_confirmation, Spree.t(:confirm_password)
+ = f.label :password_confirmation, t(".confirm_password")
= f.password_field :password_confirmation, class: "fullwidth"
= f.error_message_on :password_confirmation
\ No newline at end of file
diff --git a/app/views/spree/admin/users/edit.html.haml b/app/views/spree/admin/users/edit.html.haml
index 1457f1065a..b192342306 100644
--- a/app/views/spree/admin/users/edit.html.haml
+++ b/app/views/spree/admin/users/edit.html.haml
@@ -1,10 +1,10 @@
- content_for :page_title do
- = Spree.t(:editing_user)
+ = t(".editing_user")
- content_for :page_actions do
%li
- = button_link_to Spree.t(:back_to_users_list), spree.admin_users_path, icon: "icon-arrow-left"
+ = button_link_to t(".back_to_users_list"), spree.admin_users_path, icon: "icon-arrow-left"
%fieldset.alpha.ten.columns{"data-hook" => "admin_user_edit_general_settings"}
- %legend= Spree.t(:general_settings)
+ %legend= t(".general_settings")
%div{"data-hook" => "admin_user_edit_form_header"}
= render partial: "spree/shared/error_messages", locals: { target: @user }
%div{"data-hook" => "admin_user_edit_form"}
diff --git a/app/views/spree/admin/users/index.html.haml b/app/views/spree/admin/users/index.html.haml
index e7ef05d711..9672637e6c 100644
--- a/app/views/spree/admin/users/index.html.haml
+++ b/app/views/spree/admin/users/index.html.haml
@@ -1,8 +1,8 @@
- content_for :page_title do
- = Spree.t(:listing_users)
+ = t(".listing_users")
- content_for :page_actions do
%li
- = button_link_to Spree.t(:new_user), new_object_url, icon: "icon-plus", id: "admin_new_user_link"
+ = button_link_to t(".new_user"), new_object_url, icon: "icon-plus", id: "admin_new_user_link"
= render "admin/shared/users_sub_menu"
@@ -13,8 +13,8 @@
%col{ style: "width: 15%" }
%thead
%tr
- %th= sort_link @search,:email, Spree.t(:user), {}, {title: "users_email_title"}
- %th= sort_link @search,:enterprise_limit, t(:enterprise_limit)
+ %th= sort_link @search,:email, t(".user"), {}, {title: "users_email_title"}
+ %th= sort_link @search,:enterprise_limit, t(".enterprise_limit")
%th.actions
%tbody
- @users.each do |user|
@@ -28,13 +28,13 @@
= link_to_delete user, no_text: true
= paginate @users
- content_for :sidebar_title do
- = Spree.t(:search)
+ = t(".search")
- content_for :sidebar do
.box.align-center
= search_form_for [:admin, @search] do |f|
.field
- = f.label Spree.t(:email)
+ = f.label t(".email")
%br
= f.text_field :email_cont, class: "fullwidth"
%div
- = button Spree.t(:search), "icon-search"
+ = button t(".search"), "icon-search"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b6c2470116..1b21352146 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -209,7 +209,6 @@ en:
distributors: Distributors
distribution: Distribution
order_cycles: Order Cycles
- enterprise_limit: Enterprise Limit
bulk_order_management: Bulk Order Management
enterprises: Enterprises
enterprise_groups: Groups
@@ -225,6 +224,7 @@ en:
admin_and_handling: Admin & Handling
profile: Profile
supplier_only: Supplier Only
+ has_shopfront: Has Shopfront
weight: Weight
volume: Volume
items: Items
@@ -252,6 +252,7 @@ en:
password_confirmation: Password Confirmation
reset_password_token: Reset password token
expired: has expired, please request a new one
+ back_to_payments_list: "Back to Payments List"
actions:
create_and_add_another: "Create and Add Another"
@@ -1941,7 +1942,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using
enterprise_long_desc: "Long Description"
enterprise_long_desc_placeholder: "This is your opportunity to tell the story of your enterprise - what makes you different and wonderful? We'd suggest keeping your description to under 600 characters or 150 words."
enterprise_long_desc_length: "%{num} characters / up to 600 recommended"
- enterprise_limit: Enterprise Limit
enterprise_abn: "ABN"
enterprise_abn_placeholder: "eg. 99 123 456 789"
enterprise_acn: "ACN"
@@ -2402,6 +2402,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
validation_msg_relationship_already_established: "^That relationship is already established."
validation_msg_at_least_one_hub: "^At least one hub must be selected"
validation_msg_product_category_cant_be_blank: "^Product Category cant be blank"
+ validation_msg_tax: "^Tax Category is required"
validation_msg_tax_category_cant_be_blank: "^Tax Category can't be blank"
validation_msg_is_associated_with_an_exising_customer: "is associated with an existing customer"
content_configuration_pricing_table: "(TODO: Pricing table)"
@@ -2769,6 +2770,23 @@ See the %{link} to find out more about %{sitename}'s features and to start using
bulk_coop_packing_sheets: 'Bulk Co-op - Packing Sheets'
bulk_coop_customer_payments: 'Bulk Co-op - Customer Payments'
users:
+ index:
+ listing_users: "Listing Users"
+ new_user: "New User"
+ user: "User"
+ enterprise_limit: "Enterprise Limit"
+ search: "Search"
+ email: "Email"
+ edit:
+ editing_user: "Editing User"
+ back_to_users_list: "Back To Users List"
+ general_settings: "General Settings"
+ form:
+ email: "Email"
+ roles: "Roles"
+ enterprise_limit: "Enterprise Limit"
+ confirm_password: "Confirm Password"
+ password: "Password"
email_confirmation:
confirmation_pending: "Email confirmation is pending. We've sent a confirmation email to %{address}."
variants:
diff --git a/config/routes.rb b/config/routes.rb
index 1196e950ee..4804e4cae2 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -111,6 +111,8 @@ Openfoodnetwork::Application.routes.draw do
resources :customers, only: [:index, :update]
+ resources :enterprise_fees, only: [:destroy]
+
post '/product_images/:product_id', to: 'product_images#update_product_image'
end
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index c191322d74..1f55f8d154 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -35,7 +35,7 @@ Openfoodnetwork::Application.routes.draw do
resources :enterprise_relationships
resources :enterprise_roles
- resources :enterprise_fees do
+ resources :enterprise_fees, except: :destroy do
collection do
get :for_order_cycle
post :bulk_update, :as => :bulk_update
diff --git a/db/migrate/20181123012635_associate_customers_to_users.rb b/db/migrate/20181123012635_associate_customers_to_users.rb
new file mode 100644
index 0000000000..95fab93677
--- /dev/null
+++ b/db/migrate/20181123012635_associate_customers_to_users.rb
@@ -0,0 +1,42 @@
+# When we introduced the Customer model, we didn't associate any existing
+# customers with users that have the same email address.
+# Later we decided to create that association when users sign up. But we didn't
+# update all the existing customers. We do that now for data consistency and to
+# solve several bugs.
+#
+# - https://github.com/openfoodfoundation/openfoodnetwork/pull/2084
+# - https://github.com/openfoodfoundation/openfoodnetwork/issues/2841
+class AssociateCustomersToUsers < ActiveRecord::Migration
+ class Customer < ActiveRecord::Base
+ end
+
+ def up
+ save_customers
+ execute "UPDATE customers
+ SET user_id = spree_users.id
+ FROM spree_users
+ WHERE customers.email = spree_users.email
+ AND customers.user_id IS NULL;"
+ end
+
+ def down
+ customers = backed_up_customers
+ Customer.where(id: customers).update_all(user_id: nil)
+ end
+
+ def save_customers
+ customers = Customer.
+ joins("INNER JOIN spree_users ON customers.email = spree_users.email").
+ where(user_id: nil).all
+
+ File.write(backup_file, YAML.dump(customers))
+ end
+
+ def backed_up_customers
+ YAML.load(File.read(backup_file))
+ end
+
+ def backup_file
+ File.join("log", "customers_without_user_association.log")
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8ffc9eaf9a..92214c8281 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20181106162211) do
+ActiveRecord::Schema.define(:version => 20181123012635) do
create_table "account_invoices", :force => true do |t|
t.integer "user_id", :null => false
diff --git a/spec/controllers/api/enterprise_fees_controller_spec.rb b/spec/controllers/api/enterprise_fees_controller_spec.rb
new file mode 100644
index 0000000000..fb938d43c5
--- /dev/null
+++ b/spec/controllers/api/enterprise_fees_controller_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+module Api
+ describe EnterpriseFeesController, type: :controller do
+ include AuthenticationWorkflow
+
+ let!(:unreferenced_fee) { create(:enterprise_fee) }
+ let!(:referenced_fee) { create(:enterprise_fee) }
+ let(:product) { create(:product) }
+ let(:distributor) { create(:distributor_enterprise) }
+ let!(:product_distribution) { create(:product_distribution, product: product, distributor: distributor, enterprise_fee: referenced_fee) }
+ let(:current_user) { create(:admin_user) }
+
+ before do
+ allow(controller).to receive(:spree_current_user) { current_user }
+ end
+
+ describe "destroy" do
+ it "removes the fee" do
+ expect { spree_delete :destroy, id: unreferenced_fee.id, format: :json }
+ .to change { EnterpriseFee.count }.by -1
+ end
+
+ context "when the fee is referenced by a product distribution" do
+ it "does not remove the fee" do
+ spree_delete :destroy, id: referenced_fee.id, format: :json
+ expect(response.status).to eq 403
+ expect(response.body).to match(/That enterprise fee cannot be deleted/)
+ expect(referenced_fee.reload).to eq(referenced_fee)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/controllers/spree/admin/line_items_controller_spec.rb b/spec/controllers/spree/admin/line_items_controller_spec.rb
index 64cf29903e..a2ede41a83 100644
--- a/spec/controllers/spree/admin/line_items_controller_spec.rb
+++ b/spec/controllers/spree/admin/line_items_controller_spec.rb
@@ -90,7 +90,7 @@ describe Spree::Admin::LineItemsController, type: :controller do
it 'returns an HTML response with the order form' do
spree_put :update, params
- expect(response.body).to match(/admin_order_form_fields/)
+ expect(response.body).to match(/edit_order/)
end
end
end
diff --git a/spec/features/admin/variant_overrides_spec.rb b/spec/features/admin/variant_overrides_spec.rb
index 853104711c..60130ddc6d 100644
--- a/spec/features/admin/variant_overrides_spec.rb
+++ b/spec/features/admin/variant_overrides_spec.rb
@@ -16,10 +16,10 @@ feature %q{
let!(:producer_related) { create(:supplier_enterprise) }
let!(:producer_unrelated) { create(:supplier_enterprise) }
let!(:er1) { create(:enterprise_relationship, parent: producer, child: hub,
- permissions_list: [:create_variant_overrides])
+ permissions_list: [:create_variant_overrides])
}
let!(:er2) { create(:enterprise_relationship, parent: producer_related, child: hub,
- permissions_list: [:create_variant_overrides])
+ permissions_list: [:create_variant_overrides])
}
context "as an enterprise user" do
@@ -28,7 +28,7 @@ feature %q{
describe "selecting a hub" do
let!(:er1) { create(:enterprise_relationship, parent: hub2, child: producer_managed,
- permissions_list: [:add_to_order_cycle])
+ permissions_list: [:add_to_order_cycle])
} # This er should not confer ability to create VOs for hub2
it "displays a list of hub choices (ie. only those managed by the user)" do
@@ -338,7 +338,7 @@ feature %q{
it "shows the overridden price" do
targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop'
click_link 'Add'
- expect(page).to have_selector("table.index tbody[data-hook='admin_order_form_line_items'] tr") # Wait for JS
+ expect(page).to have_selector("table.index tbody tr") # Wait for JS
expect(page).to have_content(product.variants.first.variant_overrides.first.price)
end
end
diff --git a/spec/features/consumer/shopping/checkout_spec.rb b/spec/features/consumer/shopping/checkout_spec.rb
index 49b7c26dab..8b29d04832 100644
--- a/spec/features/consumer/shopping/checkout_spec.rb
+++ b/spec/features/consumer/shopping/checkout_spec.rb
@@ -65,19 +65,18 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
let(:user) { create(:user) }
def fill_out_form
- toggle_shipping
choose sm1.name
- toggle_payment
choose pm1.name
- toggle_details
+
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
- toggle_billing
+
check "Save as default billing address"
+
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
@@ -86,7 +85,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
select "Victoria", from: "State"
end
- toggle_shipping
check "Shipping address same as billing address?"
check "Save as default shipping address"
end
@@ -150,7 +148,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
it "checks out successfully" do
visit checkout_path
choose sm2.name
- toggle_payment
choose pm1.name
expect do
@@ -193,7 +190,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
visit checkout_path
fill_out_form
- toggle_payment
choose stripe_pm.name
end
@@ -229,7 +225,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
end
it "shows a breakdown of the order price" do
- toggle_shipping
choose sm2.name
page.should have_selector 'orderdetails .cart-total', text: with_currency(11.23)
@@ -243,7 +238,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
end
it "shows all shipping methods in order by name" do
- toggle_shipping
within '#shipping' do
expect(page).to have_selector "label", count: 4 # Three shipping methods + instructions label
labels = page.all('label').map(&:text)
@@ -255,7 +249,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
context "when shipping method requires an address" do
before do
- toggle_shipping
choose sm1.name
end
it "shows ship address forms when 'same as billing address' is unchecked" do
@@ -270,7 +263,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
it "shows shipping methods allowed by the rule" do
# No rules in effect
- toggle_shipping
page.should have_content "Frogs"
page.should have_content "Donkeys"
page.should have_content "Local"
@@ -316,7 +308,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
before do
visit checkout_path
checkout_as_guest
- toggle_payment
end
it "shows all available payment methods" do
@@ -327,8 +318,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
describe "purchasing" do
it "takes us to the order confirmation page when we submit a complete form" do
- toggle_details
-
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
@@ -336,8 +325,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
fill_in "Phone", with: "0468363090"
end
- toggle_billing
-
within "#billing" do
fill_in "Address", with: "123 Your Face"
select "Australia", from: "Country"
@@ -346,15 +333,11 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
fill_in "Postcode", with: "3066"
end
- toggle_shipping
-
within "#shipping" do
choose sm2.name
fill_in 'Any comments or special instructions?', with: "SpEcIaL NoTeS"
end
- toggle_payment
-
within "#payment" do
choose pm1.name
end
@@ -383,18 +366,16 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
context "with basic details filled" do
before do
- toggle_shipping
choose sm1.name
- toggle_payment
choose pm1.name
- toggle_details
+
within "#details" do
fill_in "First Name", with: "Will"
fill_in "Last Name", with: "Marshall"
fill_in "Email", with: "test@test.com"
fill_in "Phone", with: "0468363090"
end
- toggle_billing
+
within "#billing" do
fill_in "City", with: "Melbourne"
fill_in "Postcode", with: "3066"
@@ -402,7 +383,7 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
select "Australia", from: "Country"
select "Victoria", from: "State"
end
- toggle_shipping
+
check "Shipping address same as billing address?"
end
@@ -443,7 +424,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
expect(page).to have_selector ".transaction-fee td", text: with_currency(0.00)
expect(page).to have_selector ".total", text: with_currency(11.23)
- toggle_payment
choose "#{pm2.name} (#{with_currency(5.67)})"
expect(page).to have_selector ".transaction-fee td", text: with_currency(5.67)
@@ -465,7 +445,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: gateway_type) }
it "takes us to the order confirmation page when submitted with a valid credit card" do
- toggle_payment
fill_in 'Card Number', with: "4111111111111111"
select 'February', from: 'secrets.card_month'
select (Date.current.year+1).to_s, from: 'secrets.card_year'
@@ -480,7 +459,6 @@ feature "As a consumer I want to check out my cart", js: true, retry: 3 do
end
it "shows the payment processing failed message when submitted with an invalid credit card" do
- toggle_payment
fill_in 'Card Number', with: "9999999988887777"
select 'February', from: 'secrets.card_month'
select (Date.current.year+1).to_s, from: 'secrets.card_year'
diff --git a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb
index 39a79aba2e..80f7e52eee 100644
--- a/spec/features/consumer/shopping/embedded_shopfronts_spec.rb
+++ b/spec/features/consumer/shopping/embedded_shopfronts_spec.rb
@@ -67,7 +67,6 @@ feature "Using embedded shopfront functionality", js: true do
fill_in "Phone", with: "0456789012"
end
- toggle_billing
within "#billing" do
fill_in "Address", with: "123 Street"
select "Australia", from: "Country"
@@ -76,12 +75,10 @@ feature "Using embedded shopfront functionality", js: true do
fill_in "Postcode", with: "3066"
end
- toggle_shipping
within "#shipping" do
find('input[type="radio"]').trigger 'click'
end
- toggle_payment
within "#payment" do
find('input[type="radio"]').trigger 'click'
end
diff --git a/spec/features/consumer/shopping/variant_overrides_spec.rb b/spec/features/consumer/shopping/variant_overrides_spec.rb
index 49d1b0b2e4..ff101fd5a0 100644
--- a/spec/features/consumer/shopping/variant_overrides_spec.rb
+++ b/spec/features/consumer/shopping/variant_overrides_spec.rb
@@ -173,7 +173,6 @@ feature "shopping with variant overrides defined", js: true, retry: 3 do
fill_in "Phone", with: "0456789012"
end
- toggle_billing
within "#billing" do
fill_in "Address", with: "123 Street"
select "Australia", from: "Country"
@@ -182,12 +181,10 @@ feature "shopping with variant overrides defined", js: true, retry: 3 do
fill_in "Postcode", with: "3066"
end
- toggle_shipping
within "#shipping" do
choose sm.name
end
- toggle_payment
within "#payment" do
choose pm.name
end
@@ -201,5 +198,4 @@ feature "shopping with variant overrides defined", js: true, retry: 3 do
wait_until_enabled 'li.cart a.button'
first(:link, 'Checkout now').click
end
-
end
diff --git a/spec/support/request/checkout_workflow.rb b/spec/support/request/checkout_workflow.rb
index a38edaa6de..11a13194bc 100644
--- a/spec/support/request/checkout_workflow.rb
+++ b/spec/support/request/checkout_workflow.rb
@@ -18,16 +18,4 @@ module CheckoutWorkflow
def toggle_details
toggle_accordion :details
end
-
- def toggle_billing
- toggle_accordion :billing
- end
-
- def toggle_shipping
- toggle_accordion :shipping
- end
-
- def toggle_payment
- toggle_accordion :payment
- end
end
diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb
index 876f184644..9df7f72126 100644
--- a/spec/support/request/shop_workflow.rb
+++ b/spec/support/request/shop_workflow.rb
@@ -13,7 +13,7 @@ module ShopWorkflow
end
def set_order(order)
- ApplicationController.any_instance.stub(:session).and_return({order_id: order.id, access_token: order.token})
+ allow_any_instance_of(ApplicationController).to receive(:session).and_return({order_id: order.id, access_token: order.token})
end
def add_product_to_cart(order, product, quantity: 1)