From f4eb9cb790b8efccdc16209946c54fe05226d496 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Tue, 20 Dec 2016 12:55:39 +0000 Subject: [PATCH 01/17] Hubs display as closed when not configured for payment or shipping --- .../enterprise_injection_data.rb | 2 +- spec/features/consumer/shops_spec.rb | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/open_food_network/enterprise_injection_data.rb b/lib/open_food_network/enterprise_injection_data.rb index 938c8b3aab1..2c8b470069d 100644 --- a/lib/open_food_network/enterprise_injection_data.rb +++ b/lib/open_food_network/enterprise_injection_data.rb @@ -1,7 +1,7 @@ module OpenFoodNetwork class EnterpriseInjectionData def active_distributors - @active_distributors ||= Enterprise.distributors_with_active_order_cycles + @active_distributors ||= Enterprise.distributors_with_active_order_cycles.andand.ready_for_checkout end def earliest_closing_times diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index c9e8063e721..082bf57d792 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -6,8 +6,8 @@ let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) } let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) } - let(:d1) { create(:distributor_enterprise) } - let(:d2) { create(:distributor_enterprise) } + let!(:d1) { create(:distributor_enterprise, with_payment_and_shipping: true) } + let!(:d2) { create(:distributor_enterprise, with_payment_and_shipping: true) } let!(:order_cycle) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise)) } let!(:producer) { create(:supplier_enterprise) } let!(:er) { create(:enterprise_relationship, parent: distributor, child: producer) } @@ -57,6 +57,20 @@ end end + describe "showing available hubs" do + let!(:hub) { create(:distributor_enterprise, with_payment_and_shipping: false) } + let!(:order_cycle) { create(:simple_order_cycle, distributors: [hub], coordinator: hub) } + let!(:producer) { create(:supplier_enterprise) } + let!(:er) { create(:enterprise_relationship, parent: hub, child: producer) } + + it "does not show hubs that are not ready for checkout" do + visit shops_path + + Enterprise.ready_for_checkout.should_not include hub + page.should_not have_content hub.name + end + end + describe "filtering by product property" do let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } let!(:p1) { create(:simple_product, supplier: producer) } @@ -92,7 +106,7 @@ describe "taxon badges" do let!(:closed_oc) { create(:closed_order_cycle, distributors: [shop], variants: [p_closed.variants.first]) } let!(:p_closed) { create(:simple_product, taxons: [taxon_closed]) } - let(:shop) { create(:distributor_enterprise) } + let(:shop) { create(:distributor_enterprise, with_payment_and_shipping: true) } let(:taxon_closed) { create(:taxon, name: 'Closed') } describe "open shops" do From 4fe5e609672ba0195b7f5f4884c979ae9e0d20ed Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Tue, 20 Dec 2016 16:30:17 +0000 Subject: [PATCH 02/17] Updated controller stub to pass test --- spec/controllers/shops_controller_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/controllers/shops_controller_spec.rb b/spec/controllers/shops_controller_spec.rb index a4c66ea3a7f..2e11011c57c 100644 --- a/spec/controllers/shops_controller_spec.rb +++ b/spec/controllers/shops_controller_spec.rb @@ -6,7 +6,7 @@ let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) } before do - Enterprise.stub(:distributors_with_active_order_cycles) { [distributor] } + Enterprise.stub_chain("distributors_with_active_order_cycles.andand.ready_for_checkout") { [distributor] } end # Exclusion from actual rendered view handled in features/consumer/home From 1f2c6f2a85e2562f9aebfa269814bf24005abe7e Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Tue, 4 Apr 2017 00:45:01 +0100 Subject: [PATCH 03/17] Ensure shops display as closed when not configured for sales squashme squashme squash squash squash --- app/controllers/base_controller.rb | 7 +++++++ spec/controllers/shop_controller_spec.rb | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/controllers/base_controller.rb b/app/controllers/base_controller.rb index 36084c0225b..e5535b71ad1 100644 --- a/app/controllers/base_controller.rb +++ b/app/controllers/base_controller.rb @@ -26,6 +26,8 @@ def set_order_cycles @order_cycles = OrderCycle.with_distributor(@distributor).active .order(@distributor.preferred_shopfront_order_cycle_order) + ensure_shop_ready + applicator = OpenFoodNetwork::TagRuleApplicator.new(@distributor, "FilterOrderCycles", current_customer.andand.tag_list) applicator.filter!(@order_cycles) @@ -34,4 +36,9 @@ def set_order_cycles current_order(true).set_order_cycle! @order_cycles.first end end + + def ensure_shop_ready + # Don't display order cycles if shop is not ready for checkout + @order_cycles = {} unless @distributor.ready_for_checkout? + end end diff --git a/spec/controllers/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb index c3784df428d..eac8a399d22 100644 --- a/spec/controllers/shop_controller_spec.rb +++ b/spec/controllers/shop_controller_spec.rb @@ -1,7 +1,9 @@ require 'spec_helper' describe ShopController do - let(:distributor) { create(:distributor_enterprise) } + let!(:pm) { create(:payment_method) } + let!(:sm) { create(:shipping_method) } + let(:distributor) { create(:distributor_enterprise, payment_methods: [pm], shipping_methods: [sm]) } it "redirects to the home page if no distributor is selected" do spree_get :show From 81877fedb6dcf0f09eca599d5bdd59fa5b49d380 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 12 Apr 2017 15:00:21 +1000 Subject: [PATCH 04/17] Remove useless `andand` called on scope --- lib/open_food_network/enterprise_injection_data.rb | 2 +- spec/controllers/shops_controller_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/open_food_network/enterprise_injection_data.rb b/lib/open_food_network/enterprise_injection_data.rb index 2c8b470069d..3d15344472d 100644 --- a/lib/open_food_network/enterprise_injection_data.rb +++ b/lib/open_food_network/enterprise_injection_data.rb @@ -1,7 +1,7 @@ module OpenFoodNetwork class EnterpriseInjectionData def active_distributors - @active_distributors ||= Enterprise.distributors_with_active_order_cycles.andand.ready_for_checkout + @active_distributors ||= Enterprise.distributors_with_active_order_cycles.ready_for_checkout end def earliest_closing_times diff --git a/spec/controllers/shops_controller_spec.rb b/spec/controllers/shops_controller_spec.rb index 2e11011c57c..2b99c5f62ca 100644 --- a/spec/controllers/shops_controller_spec.rb +++ b/spec/controllers/shops_controller_spec.rb @@ -6,7 +6,7 @@ let!(:invisible_distributor) { create(:distributor_enterprise, visible: false) } before do - Enterprise.stub_chain("distributors_with_active_order_cycles.andand.ready_for_checkout") { [distributor] } + Enterprise.stub_chain("distributors_with_active_order_cycles.ready_for_checkout") { [distributor] } end # Exclusion from actual rendered view handled in features/consumer/home From 4809237eccfc542d9902d1afb0b3b92c6a5ebd00 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 12 Apr 2017 15:17:42 +1000 Subject: [PATCH 05/17] Fast fail `set_order_cycles` if distributor not ready --- app/controllers/base_controller.rb | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/controllers/base_controller.rb b/app/controllers/base_controller.rb index e5535b71ad1..7f9a0f2df61 100644 --- a/app/controllers/base_controller.rb +++ b/app/controllers/base_controller.rb @@ -23,11 +23,14 @@ class BaseController < ApplicationController private def set_order_cycles + unless @distributor.ready_for_checkout? + @order_cycles = OrderCycle.where('false') + return + end + @order_cycles = OrderCycle.with_distributor(@distributor).active .order(@distributor.preferred_shopfront_order_cycle_order) - ensure_shop_ready - applicator = OpenFoodNetwork::TagRuleApplicator.new(@distributor, "FilterOrderCycles", current_customer.andand.tag_list) applicator.filter!(@order_cycles) @@ -36,9 +39,4 @@ def set_order_cycles current_order(true).set_order_cycle! @order_cycles.first end end - - def ensure_shop_ready - # Don't display order cycles if shop is not ready for checkout - @order_cycles = {} unless @distributor.ready_for_checkout? - end end From a4e4e1ec68e6df09463406c3756d4f142c0e5267 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Wed, 11 Jan 2017 13:16:46 +0000 Subject: [PATCH 06/17] Require OC name --- app/views/admin/order_cycles/_exchange_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/order_cycles/_exchange_form.html.haml b/app/views/admin/order_cycles/_exchange_form.html.haml index c1fc1a7a48d..1275103a503 100644 --- a/app/views/admin/order_cycles/_exchange_form.html.haml +++ b/app/views/admin/order_cycles/_exchange_form.html.haml @@ -14,7 +14,7 @@ %td.tags.panel-toggle.text-center{ name: "tags", ng: { if: 'enterprises[exchange.enterprise_id].managed || order_cycle.viewing_as_coordinator' } } {{ exchange.tags.length }} %td.collection-details - = text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35 + = text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_time', 'required' => 'required', 'placeholder' => t('.pickup_time_placeholder'), 'ng-model' => 'exchange.pickup_time', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator', 'maxlength' => 35 %span.icon-question-sign{'ofn-with-tip' => t('admin.order_cycles.edit.pickup_time_tip')} %br/ = text_field_tag 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_{{ $index }}_pickup_instructions', 'placeholder' => t('.pickup_instructions_placeholder'), 'ng-model' => 'exchange.pickup_instructions', 'ng-disabled' => '!enterprises[exchange.enterprise_id].managed && !order_cycle.viewing_as_coordinator' From accb3076e97dda1c2fcd872a9d74c03e770e0dc5 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Wed, 11 Jan 2017 13:28:54 +0000 Subject: [PATCH 07/17] Updated translations --- .../javascripts/admin/order_cycles/controllers/create.js.coffee | 2 +- config/locales/en-GB.yml | 2 ++ config/locales/en.yml | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee index e0f7cf96b63..f5bc6aeb4dd 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee @@ -12,7 +12,7 @@ angular.module('admin.orderCycles') $scope.StatusMessage = StatusMessage $scope.$watch 'order_cycle_form.$dirty', (newValue) -> - StatusMessage.display 'notice', 'You have unsaved changes' if newValue + StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue $scope.loaded = -> Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded diff --git a/config/locales/en-GB.yml b/config/locales/en-GB.yml index f48248ddd78..8215019a844 100644 --- a/config/locales/en-GB.yml +++ b/config/locales/en-GB.yml @@ -70,6 +70,8 @@ en-GB: clear_all: Clear All start_date: "Start Date" end_date: "End Date" + unsaved_changes: "You have unsaved changes" + form_invalid: "Form contains missing or invalid fields" columns: Columns actions: Actions viewing: "Viewing: %{current_view_name}" diff --git a/config/locales/en.yml b/config/locales/en.yml index 40a3549d603..e16099fe602 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -105,6 +105,8 @@ en: clear_all: Clear All start_date: "Start Date" end_date: "End Date" + unsaved_changes: "You have unsaved changes" + form_invalid: "Form contains missing or invalid fields" columns: Columns actions: Actions From fa5ed529cb83ac704b446e82d258ba10b2bc5c63 Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Wed, 11 Jan 2017 13:30:28 +0000 Subject: [PATCH 08/17] Added OC form validation --- .../admin/order_cycles/controllers/create.js.coffee | 3 +++ .../admin/order_cycles/controllers/edit.js.coffee | 5 ++++- .../order_cycles/controllers/simple_create.js.coffee | 5 ++++- .../admin/order_cycles/controllers/simple_edit.js.coffee | 5 ++++- .../admin/utils/services/status_message.js.coffee | 8 ++++++++ app/assets/javascripts/templates/admin/save_bar.html.haml | 5 ++++- app/views/admin/order_cycles/edit.html.haml | 4 ++-- app/views/admin/order_cycles/new.html.haml | 2 +- spec/features/admin/order_cycles_spec.rb | 7 +++++++ 9 files changed, 37 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee index f5bc6aeb4dd..d4e1a2beb10 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/create.js.coffee @@ -14,6 +14,9 @@ angular.module('admin.orderCycles') $scope.$watch 'order_cycle_form.$dirty', (newValue) -> StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue + $scope.$watch 'order_cycle_form.$valid', (isValid) -> + StatusMessage.setValidation(isValid) + $scope.loaded = -> Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded diff --git a/app/assets/javascripts/admin/order_cycles/controllers/edit.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/edit.js.coffee index 0e1a0ab45c2..d43e26c4426 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/edit.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/edit.js.coffee @@ -13,7 +13,10 @@ angular.module('admin.orderCycles') $scope.StatusMessage = StatusMessage $scope.$watch 'order_cycle_form.$dirty', (newValue) -> - StatusMessage.display 'notice', 'You have unsaved changes' if newValue + StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue + + $scope.$watch 'order_cycle_form.$valid', (isValid) -> + StatusMessage.setValidation(isValid) $scope.loaded = -> Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple_create.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple_create.js.coffee index 7a0a03f2bfe..0d1f9482b6a 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/simple_create.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple_create.js.coffee @@ -8,7 +8,10 @@ angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl" $scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id) $scope.$watch 'order_cycle_form.$dirty', (newValue) -> - StatusMessage.display 'notice', 'You have unsaved changes' if newValue + StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue + + $scope.$watch 'order_cycle_form.$valid', (isValid) -> + StatusMessage.setValidation(isValid) $scope.init = (enterprises) -> enterprise = enterprises[Object.keys(enterprises)[0]] diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee index 7df7ddff343..d950d931190 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee @@ -10,7 +10,10 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", $scope.init() $scope.$watch 'order_cycle_form.$dirty', (newValue) -> - StatusMessage.display 'notice', 'You have unsaved changes' if newValue + StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue + + $scope.$watch 'order_cycle_form.$valid', (isValid) -> + StatusMessage.setValidation(isValid) $scope.loaded = -> Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded diff --git a/app/assets/javascripts/admin/utils/services/status_message.js.coffee b/app/assets/javascripts/admin/utils/services/status_message.js.coffee index 6aac046a7fe..0d752cdcd97 100644 --- a/app/assets/javascripts/admin/utils/services/status_message.js.coffee +++ b/app/assets/javascripts/admin/utils/services/status_message.js.coffee @@ -11,6 +11,14 @@ angular.module("admin.utils").factory "StatusMessage", ($timeout) -> text: "" style: {} + invalidMessage: "" + + setValidation: (isValid) -> + if isValid + StatusMessage.invalidMessage = '' + else + StatusMessage.invalidMessage = t("admin.form_invalid") + active: -> @statusMessage.text != '' diff --git a/app/assets/javascripts/templates/admin/save_bar.html.haml b/app/assets/javascripts/templates/admin/save_bar.html.haml index 12ccd4537c6..e877e847473 100644 --- a/app/assets/javascripts/templates/admin/save_bar.html.haml +++ b/app/assets/javascripts/templates/admin/save_bar.html.haml @@ -1,6 +1,9 @@ #save-bar.animate-show{ ng: { show: 'dirty || persist || StatusMessage.active()' } } .container .eight.columns.alpha - %h5#status-message{ ng: { style: 'StatusMessage.statusMessage.style' } } + %h5#status-message{ ng: { show: "StatusMessage.invalidMessage == ''", style: 'StatusMessage.statusMessage.style' } } {{ StatusMessage.statusMessage.text || " " }} + %h5#status-message{ ng: { show: "StatusMessage.invalidMessage !== ''" }, style: 'color: #da5354' } + {{ StatusMessage.invalidMessage || " " }} .eight.columns.omega.text-right{ ng: { transclude: true } } + diff --git a/app/views/admin/order_cycles/edit.html.haml b/app/views/admin/order_cycles/edit.html.haml index 34f64c1ee71..ddfd10b38a1 100644 --- a/app/views/admin/order_cycles/edit.html.haml +++ b/app/views/admin/order_cycles/edit.html.haml @@ -28,8 +28,8 @@ = form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f| %save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" } - %input.red{ type: "button", value: t(:update), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty" } } - %input.red{ type: "button", value: t('.update_and_close'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty" } } + %input.red{ type: "button", value: t(:update), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } } + %input.red{ type: "button", value: t('.update_and_close'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } } %input{ type: "button", ng: { value: "order_cycle_form.$dirty ? 'Cancel' : 'Close'", click: "cancel('#{main_app.admin_order_cycles_path}')" } } - if order_cycles_simple_form diff --git a/app/views/admin/order_cycles/new.html.haml b/app/views/admin/order_cycles/new.html.haml index 6bc0946f01d..a127ab5088b 100644 --- a/app/views/admin/order_cycles/new.html.haml +++ b/app/views/admin/order_cycles/new.html.haml @@ -7,7 +7,7 @@ = form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.orderCycles', 'ng-controller' => ng_controller, name: 'order_cycle_form'} do |f| %save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" } - %input.red{ type: "button", value: t(:create), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty" } } + %input.red{ type: "button", value: t(:create), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } } %input{ type: "button", ng: { value: "order_cycle_form.$dirty ? 'Cancel' : 'Close'", click: "cancel('#{main_app.admin_order_cycles_path}')" } } - if order_cycles_simple_form diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 212fafd0262..d9bfdfd3453 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -350,6 +350,8 @@ fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'New instructions 0' fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'New time 1' fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'New instructions 1' + fill_in 'order_cycle_outgoing_exchange_2_pickup_time', with: 'New time 2' + fill_in 'order_cycle_outgoing_exchange_2_pickup_instructions', with: 'New instructions 2' page.find("table.exchanges tr.distributor-#{distributor.id} td.tags").click within ".exchange-tags" do @@ -616,6 +618,11 @@ select 'Permitted distributor', from: 'new_distributor_id' click_button 'Add distributor' + fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time' + fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions' + fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'pickup time 2' + fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'pickup instructions' + # Should only have suppliers / distributors listed which the user is managing or # has E2E permission to add products to order cycles page.should_not have_select 'new_supplier_id', with_options: [supplier_unmanaged.name] From 0d1547f439a234344d69d31c945100c084a76ccf Mon Sep 17 00:00:00 2001 From: Matt-Yorkley Date: Sat, 1 Apr 2017 11:19:52 +0100 Subject: [PATCH 09/17] Require OC ready_for in simple OC UI --- app/views/admin/order_cycles/_simple_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/order_cycles/_simple_form.html.haml b/app/views/admin/order_cycles/_simple_form.html.haml index 3d58c0249e5..61b4e04e4f2 100644 --- a/app/views/admin/order_cycles/_simple_form.html.haml +++ b/app/views/admin/order_cycles/_simple_form.html.haml @@ -4,7 +4,7 @@ .alpha.two.columns = label_tag t('.ready_for') .six.columns - = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => t('.ready_for_placeholder'), 'ng-model' => 'outgoing_exchange.pickup_time', 'size' => 30, 'maxlength' => 35 + = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'required' => 'required', 'placeholder' => t('.ready_for_placeholder'), 'ng-model' => 'outgoing_exchange.pickup_time', 'size' => 30, 'maxlength' => 35 %span.icon-question-sign{'ofn-with-tip' => t('admin.order_cycles.edit.pickup_time_tip')} .two.columns = label_tag t('.customer_instructions') From 4a9c17cb2838327d228ac3e75ee68bc46deddf60 Mon Sep 17 00:00:00 2001 From: Pierre de Lacroix Date: Thu, 23 Mar 2017 03:55:32 +0100 Subject: [PATCH 10/17] better tax aggregation --- app/helpers/checkout_helper.rb | 9 +++---- app/models/spree/adjustment_decorator.rb | 24 +++++++++++++++++-- app/models/spree/order_decorator.rb | 12 +++++----- .../enterprise_fee_applicator.rb | 12 +--------- 4 files changed, 32 insertions(+), 25 deletions(-) diff --git a/app/helpers/checkout_helper.rb b/app/helpers/checkout_helper.rb index f55a619f2b8..eb4cb1fb65a 100644 --- a/app/helpers/checkout_helper.rb +++ b/app/helpers/checkout_helper.rb @@ -54,12 +54,9 @@ def display_line_item_tax_rates(line_item) end def display_adjustment_tax_rates(adjustment) - tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2) - if tax_rate == 0 || tax_rate.infinite? - "" - else - number_to_percentage(tax_rate * 100, :precision => 1) - end + tax_rates = adjustment.tax_rates + return "" if adjustment.amount == adjustment.included_tax + tax_rates.map { |tr| number_to_percentage(tr.amount * 100, :precision => 1) }.join(", ") end def display_adjustment_amount(adjustment) diff --git a/app/models/spree/adjustment_decorator.rb b/app/models/spree/adjustment_decorator.rb index 093f1c86fd3..4ad456ba12a 100644 --- a/app/models/spree/adjustment_decorator.rb +++ b/app/models/spree/adjustment_decorator.rb @@ -34,10 +34,30 @@ def has_tax? included_tax > 0 end - def display_included_tax - Spree::Money.new(included_tax, { :currency => currency }) + def tax_rates + case originator + when Spree::TaxRate + [originator] + when EnterpriseFee + case source + when Spree::LineItem + tax_category = originator.inherits_tax_category? ? source.product.tax_category : originator.tax_category + return tax_category ? tax_category.tax_rates.match(source.order) : [] + when Spree::Order + return originator.tax_category ? originator.tax_category.tax_rates.match(source) : [] + end + else + [find_closest_tax_rate_from_included_tax] + end end + def find_closest_tax_rate_from_included_tax + approximation = (included_tax / (amount - included_tax)) + return nil if approximation.infinite? or approximation.zero? + Spree::TaxRate.order("ABS(amount - #{approximation})").first + end + + def self.without_callbacks skip_callback :save, :after, :update_adjustable skip_callback :destroy, :after, :update_adjustable diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 8212840a8d4..e1135853eec 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -234,12 +234,12 @@ def tax_adjustments def tax_adjustment_totals tax_adjustments.each_with_object(Hash.new) do |adjustment, hash| - if adjustment.originator_type == "Spree::TaxRate" - tax_rate = adjustment.originator.amount - else - tax_rate = (adjustment.included_tax / (adjustment.amount - adjustment.included_tax)).round(2) - end - hash.update({tax_rate => adjustment.included_tax}) { |_tax_rate, amount1, amount2| amount1 + amount2 } + tax_rates = adjustment.tax_rates + tax_rates_hash = Hash[tax_rates.collect do |tax_rate| + tax_amount = tax_rates.one? ? adjustment.included_tax : tax_rate.compute_tax(adjustment.amount) + [tax_rate.amount, tax_amount] + end] + hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 } end end diff --git a/lib/open_food_network/enterprise_fee_applicator.rb b/lib/open_food_network/enterprise_fee_applicator.rb index 06e71dd21c2..95bea1e3743 100644 --- a/lib/open_food_network/enterprise_fee_applicator.rb +++ b/lib/open_food_network/enterprise_fee_applicator.rb @@ -32,21 +32,11 @@ def base_adjustment_label end def adjustment_tax(adjustable, adjustment) - tax_rates = rates_for(adjustable) + tax_rates = adjustment.tax_rates tax_rates.select(&:included_in_price).sum do |rate| rate.compute_tax adjustment.amount end end - - def rates_for(adjustable) - case adjustable - when Spree::LineItem - tax_category = enterprise_fee.inherits_tax_category? ? adjustable.product.tax_category : enterprise_fee.tax_category - return tax_category ? tax_category.tax_rates.match(adjustable.order) : [] - when Spree::Order - return enterprise_fee.tax_category ? enterprise_fee.tax_category.tax_rates.match(adjustable) : [] - end - end end end From e854eb0426b9cc2a1965c52a03f0f6c04ff0ea6f Mon Sep 17 00:00:00 2001 From: Pierre de Lacroix Date: Thu, 6 Apr 2017 10:57:10 +0200 Subject: [PATCH 11/17] add tests for methods Spree::Order#tax_adjustment_totals and Spree::Adjustment#find_closest_tax_rate_from_included_tax --- spec/models/spree/adjustment_spec.rb | 17 +++++++++++ spec/models/spree/order_spec.rb | 44 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/spec/models/spree/adjustment_spec.rb b/spec/models/spree/adjustment_spec.rb index c3e2ae83042..64113c62908 100644 --- a/spec/models/spree/adjustment_spec.rb +++ b/spec/models/spree/adjustment_spec.rb @@ -1,3 +1,5 @@ +require 'spec_helper' + module Spree describe Adjustment do it "has metadata" do @@ -279,6 +281,21 @@ module Spree adjustment.included_tax.should == 10.00 end end + + describe "getting the corresponding tax rate" do + let!(:adjustment_with_tax) { create(:adjustment, amount: 50, included_tax: 10) } + let!(:adjustment_without_tax) { create(:adjustment, amount: 50, included_tax: 0) } + let!(:tax_rate) { create(:tax_rate, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25) } + let!(:other_tax_rate) { create(:tax_rate, calculator: Spree::Calculator::DefaultTax.new, amount: 0.3) } + + it "returns nil if there is no included tax" do + adjustment_without_tax.find_closest_tax_rate_from_included_tax.should == nil + end + + it "returns the most accurate tax rate" do + adjustment_with_tax.find_closest_tax_rate_from_included_tax.should == tax_rate + end + end end end end diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index b8ea3ae0ee7..89223805665 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -276,6 +276,50 @@ end end + describe "getting a hash of all taxes" do + let(:zone) { create(:zone_with_member) } + let(:coordinator) { create(:distributor_enterprise, charges_sales_tax: true) } + + let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) } + let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) } + let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) } + let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) } + let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) } + let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) } + + let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) } + let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) } + let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) } + + let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) } + let!(:order) { create(:order, shipping_method: shipping_method, bill_address: create(:address), order_cycle: order_cycle, distributor: coordinator) } + let!(:line_item) { create(:line_item, order: order, variant: variant, price: 44.0) } + + before do + Spree::Config.shipment_inc_vat = true + Spree::Config.shipping_tax_rate = tax_rate15.amount + order.create_shipment! + Spree::TaxRate.adjust(order) + order.reload.update_distribution_charge! + end + + it "returns a hash with all 3 taxes" do + order.tax_adjustment_totals.size.should == 3 + end + + it "contains tax on line_item" do + order.tax_adjustment_totals[tax_rate10.amount].should == 4.0 + end + + it "contains tax on shipping_fee" do + order.tax_adjustment_totals[tax_rate15.amount].should == 6.0 + end + + it "contains tax on enterprise_fee" do + order.tax_adjustment_totals[tax_rate20.amount].should == 8.0 + end + end + describe "setting the distributor" do it "sets the distributor when no order cycle is set" do d = create(:distributor_enterprise) From 49c19a1d6a3876aeaf27d06514440dbc5304cfea Mon Sep 17 00:00:00 2001 From: Pierre de Lacroix Date: Mon, 3 Apr 2017 15:47:35 +0200 Subject: [PATCH 12/17] update wkhtmltopdf-binary and wicked_pdf --- Gemfile.lock | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 20366a91073..9f130f9f73b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -643,9 +643,8 @@ GEM whenever (0.9.2) activesupport (>= 2.3.4) chronic (>= 0.6.3) - wicked_pdf (0.11.0) - rails - wkhtmltopdf-binary (0.9.9.3) + wicked_pdf (1.1.0) + wkhtmltopdf-binary (0.12.3.1) xml-simple (1.1.4) xpath (2.0.0) nokogiri (~> 1.3) From 78ffdec693fc7cd5aa0fa815a6809abf33255203 Mon Sep 17 00:00:00 2001 From: Em-AK Date: Wed, 29 Mar 2017 04:22:11 +0200 Subject: [PATCH 13/17] Force english locale in test environment --- config/environments/test.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/config/environments/test.rb b/config/environments/test.rb index 228bd1736dc..1f725304d0a 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -35,6 +35,7 @@ # Tests assume English text on the site. config.i18n.default_locale = "en" + I18n.locale = config.i18n.locale = config.i18n.default_locale # Use SQL instead of Active Record's schema dumper when creating the test database. # This is necessary if your schema can't be completely dumped by the schema dumper, From c72d17dc83324a0dfc6b883b6dd4bfb48e0c8674 Mon Sep 17 00:00:00 2001 From: Em-AK Date: Wed, 29 Mar 2017 04:58:37 +0200 Subject: [PATCH 14/17] Run karma task only in test environment and fails otherwise, as it needs the defaults defined in test environment --- README.md | 8 ++++++++ lib/tasks/karma.rake | 12 ++++++++++-- script/ci/run_js_tests.sh | 2 +- script/karma | 13 +++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100755 script/karma diff --git a/README.md b/README.md index c572aae193a..07fb9e4b41a 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,14 @@ The site is configured to use startup time while Rails loads. See the Zeus github page for usage instructions. +Once [npm dependencies are +installed](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Karma), AngularJS tests can be run with: + + ./script/karma run + +If you want karma to automatically rerun the tests on file modification, use: + + ./script/karma start ## Credits diff --git a/lib/tasks/karma.rake b/lib/tasks/karma.rake index ec994d37fc2..54e47e91108 100644 --- a/lib/tasks/karma.rake +++ b/lib/tasks/karma.rake @@ -1,14 +1,22 @@ namespace :karma do - task :start => :environment do + task :start => :environment do |task| + continue_only_in_test_env task with_tmp_config :start end - task :run => :environment do + task :run => :environment do |task| + continue_only_in_test_env task with_tmp_config :start, "--single-run" end private + def continue_only_in_test_env task + if Rails.env != 'test' + raise "Task must be called in test environment:\n bundle exec rake #{task.name} RAILS_ENV=test" + end + end + def with_tmp_config(command, args = nil) Tempfile.open('karma_unit.js', Rails.root.join('tmp') ) do |f| f.write unit_js(application_spec_files << i18n_file) diff --git a/script/ci/run_js_tests.sh b/script/ci/run_js_tests.sh index c4a03403b97..cd274eaf47e 100755 --- a/script/ci/run_js_tests.sh +++ b/script/ci/run_js_tests.sh @@ -14,4 +14,4 @@ echo "--- Bundling" bundle install echo "--- Running tests" -bundle exec rake karma:run +./script/karma run diff --git a/script/karma b/script/karma new file mode 100755 index 00000000000..8df2a35fbc7 --- /dev/null +++ b/script/karma @@ -0,0 +1,13 @@ +#!/bin/sh + +task="$1" + +if [ "$task" = "run" ] || [ "$task" = "start" ]; then + exec bundle exec rake "karma:$task" RAILS_ENV=test +else + echo "Usage:" + echo " $0 run # to run the tests once" + echo " $0 start # to run the tests on every file modification" + exit 1 +fi + From 2fae467e9af4653d1326813570eb8ccd8514b5b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Turbelin?= Date: Tue, 21 Mar 2017 00:15:43 +0100 Subject: [PATCH 15/17] Translate ResetPasswordConfirmation mail --- .../user_mailer/reset_password_instructions.text.erb | 5 +++++ config/locales/en.yml | 10 ++++++++++ 2 files changed, 15 insertions(+) create mode 100644 app/views/spree/user_mailer/reset_password_instructions.text.erb diff --git a/app/views/spree/user_mailer/reset_password_instructions.text.erb b/app/views/spree/user_mailer/reset_password_instructions.text.erb new file mode 100644 index 00000000000..1d3075abb15 --- /dev/null +++ b/app/views/spree/user_mailer/reset_password_instructions.text.erb @@ -0,0 +1,5 @@ +<%= t('.request_sent_text') %> +<%= t('.link_text') %> +<%= @edit_password_reset_url %> + +<%= t('.issue_text') %> diff --git a/config/locales/en.yml b/config/locales/en.yml index e16099fe602..a724c198640 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1596,3 +1596,13 @@ Please follow the instructions there to make your enterprise visible on the Open orders: invoice: tax_invoice: "TAX INVOICE: " + user_mailer: + reset_password_instructions: + request_sent_text: | + A request to reset your password has been made. + If you did not make this request, simply ignore this email. + link_text: > + If you did make this request just click the link below: + issue_text: | + If the above URL does not work try copying and pasting it into your browser. + If you continue to have problems please feel free to contact us. From b302deb7a3524c786bb54d82a97f509ca88ee2d6 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 26 Apr 2017 12:12:55 +1000 Subject: [PATCH 16/17] Add UserMailer specs adapted from Spree code --- spec/mailers/user_mailer_spec.rb | 35 +++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index 97e0eb4430c..5e389b71bf4 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -2,7 +2,7 @@ describe Spree::UserMailer do let(:user) { build(:user) } - + after do ActionMailer::Base.deliveries.clear end @@ -17,4 +17,37 @@ Spree::UserMailer.signup_confirmation(user).deliver ActionMailer::Base.deliveries.count.should == 1 end + + # adapted from https://github.com/spree/spree_auth_devise/blob/70737af/spec/mailers/user_mailer_spec.rb + describe '#reset_password_instructions' do + describe 'message contents' do + before do + @message = described_class.reset_password_instructions(user) + end + + context 'subject includes' do + it 'translated devise instructions' do + expect(@message.subject).to include "Password Reset Instructions" + end + + it 'Spree site name' do + expect(@message.subject).to include Spree::Config[:site_name] + end + end + + context 'body includes' do + it 'password reset url' do + expect(@message.body.raw_source).to include root_url + "user/spree_user/password/edit" + end + end + end + + describe 'legacy support for User object' do + it 'sends an email' do + expect do + Spree::UserMailer.reset_password_instructions(user).deliver + end.to change(ActionMailer::Base.deliveries, :size).by(1) + end + end + end end From d91c3d124113b46d57c335c7114f06a41965d936 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Wed, 26 Apr 2017 12:14:59 +1000 Subject: [PATCH 17/17] Format reset password instructions like Spree --- .../spree/user_mailer/reset_password_instructions.text.erb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/views/spree/user_mailer/reset_password_instructions.text.erb b/app/views/spree/user_mailer/reset_password_instructions.text.erb index 1d3075abb15..595b1cc6aad 100644 --- a/app/views/spree/user_mailer/reset_password_instructions.text.erb +++ b/app/views/spree/user_mailer/reset_password_instructions.text.erb @@ -1,5 +1,7 @@ <%= t('.request_sent_text') %> + <%= t('.link_text') %> + <%= @edit_password_reset_url %> <%= t('.issue_text') %>