From 7313aecd1908cd604a8110d7c00f55037edb3625 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Fri, 3 Oct 2014 12:19:58 +1000 Subject: [PATCH 01/42] add route checking, not working yet... --- .../enterprises/controllers/enterprise_controller.js.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee index c5b38191ba..959708e146 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee @@ -1,8 +1,10 @@ angular.module("admin.enterprises") - .controller "enterpriseCtrl", ($scope, Enterprise, PaymentMethods, ShippingMethods) -> + .controller "enterpriseCtrl", ($scope, $rootScope, Enterprise, PaymentMethods, ShippingMethods) -> $scope.Enterprise = Enterprise.enterprise $scope.PaymentMethods = PaymentMethods.paymentMethods $scope.ShippingMethods = ShippingMethods.shippingMethods + $scope.$on "$routeChangeStart", (event, newUrl, oldUrl) -> + event.preventDefault() for payment_method in $scope.PaymentMethods payment_method.selected = payment_method.id in $scope.Enterprise.payment_method_ids @@ -32,4 +34,4 @@ angular.module("admin.enterprises") $scope.ShippingMethods.reduce (count, shipping_method) -> count++ if shipping_method.selected count - , 0 \ No newline at end of file + , 0 From 01c179856a4906deb5e2fda80e3ceaabc77689f9 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sun, 12 Oct 2014 21:19:59 +1100 Subject: [PATCH 02/42] set maxlength for short description field --- app/views/admin/enterprises/_form.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/admin/enterprises/_form.html.haml b/app/views/admin/enterprises/_form.html.haml index 921807b425..9a3cf1bf39 100644 --- a/app/views/admin/enterprises/_form.html.haml +++ b/app/views/admin/enterprises/_form.html.haml @@ -177,7 +177,7 @@ .alpha.three.columns = f.label :description, 'Short Description' .omega.eight.columns - = f.text_field :description, placeholder: 'Tell us about your enterprise in one or two sentences' + = f.text_field :description, maxlength: 255, placeholder: 'Tell us about your enterprise in one or two sentences' .row .alpha.three.columns = f.label :long_description, 'About Us' From 5dd9879b96abd020c82d63bb1a4af8802cafca6f Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sun, 12 Oct 2014 21:57:01 +1100 Subject: [PATCH 03/42] validate description max lenth --- app/models/enterprise.rb | 2 +- spec/models/enterprise_spec.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index dfb7945878..3d1d8ff9bd 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -1,7 +1,6 @@ class Enterprise < ActiveRecord::Base TYPES = %w(full single profile) ENTERPRISE_SEARCH_RADIUS = 100 - self.inheritance_column = nil acts_as_gmappable :process_geocoding => false @@ -52,6 +51,7 @@ class Enterprise < ActiveRecord::Base validates :email, presence: true validates_presence_of :owner validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? } + validates_length_of :description, :maximum => 255 before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? } before_validation :set_unused_address_fields diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index 241d1fafc7..fff57f6f21 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -86,6 +86,7 @@ describe Enterprise do subject { FactoryGirl.create(:distributor_enterprise, :address => FactoryGirl.create(:address)) } it { should validate_presence_of(:name) } it { should validate_presence_of(:email) } + it { should validate_length_of(:description, :maximum => 255) } it "requires an owner" do expect{ From 5e4186587117eb57917e5f85045e3be2a43152cb Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Tue, 14 Oct 2014 00:25:46 +1100 Subject: [PATCH 04/42] add utils angular module and navigation check factory --- app/assets/javascripts/admin/all.js | 1 + .../enterprise_controller.js.coffee | 10 +++-- .../admin/enterprises/enterprises.js.coffee | 2 +- .../utils/services/navigation_check.js.coffee | 37 +++++++++++++++++++ .../javascripts/admin/utils/utils.js.coffee | 1 + 5 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/admin/utils/services/navigation_check.js.coffee create mode 100644 app/assets/javascripts/admin/utils/utils.js.coffee diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index f8d3ceb721..7dc9d1116f 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -22,6 +22,7 @@ //= require ./payment_methods/payment_methods //= require ./products/products //= require ./shipping_methods/shipping_methods +//= require ./utils/utils //= require ./users/users //= require textAngular.min.js //= require textAngular-sanitize.min.js diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee index 045b6e3422..6558c789a2 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee @@ -1,11 +1,15 @@ angular.module("admin.enterprises") - .controller "enterpriseCtrl", ($scope, Enterprise, longDescription, PaymentMethods, ShippingMethods) -> + .controller "enterpriseCtrl", ($scope, longDescription, Enterprise, PaymentMethods, ShippingMethods, NavigationCheck) -> $scope.Enterprise = Enterprise.enterprise $scope.PaymentMethods = PaymentMethods.paymentMethods $scope.ShippingMethods = ShippingMethods.shippingMethods + # htmlVariable is used by textAngular wysiwyg for the long descrtiption. $scope.htmlVariable = longDescription - $scope.$on "$routeChangeStart", (event, newUrl, oldUrl) -> - event.preventDefault() + # Provide a callback for a warning message displayed when leaving the page. + navigationCallback = -> + "You are editing an enterprise!" + + NavigationCheck.register navigationCallback for payment_method in $scope.PaymentMethods payment_method.selected = payment_method.id in $scope.Enterprise.payment_method_ids diff --git a/app/assets/javascripts/admin/enterprises/enterprises.js.coffee b/app/assets/javascripts/admin/enterprises/enterprises.js.coffee index 9b67bc14f4..e1e43854d1 100644 --- a/app/assets/javascripts/admin/enterprises/enterprises.js.coffee +++ b/app/assets/javascripts/admin/enterprises/enterprises.js.coffee @@ -1 +1 @@ -angular.module("admin.enterprises", ["admin.payment_methods", "admin.shipping_methods", "admin.users", "textAngular"]) \ No newline at end of file +angular.module("admin.enterprises", ["admin.payment_methods", "admin.utils", "admin.shipping_methods", "admin.users", "textAngular"]) \ No newline at end of file diff --git a/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee b/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee new file mode 100644 index 0000000000..1aea4e087f --- /dev/null +++ b/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee @@ -0,0 +1,37 @@ +angular.module("admin.utils") + .factory "NavigationCheck", ($window, $rootScope) -> + callbacks = [] + + # Action for regular browser navigation. + onBeforeUnloadHandler = ($event) -> + message = getMessage() + if message + ($event or $window.event).preventDefault() + message + + # Action for angular navigation. + locationChangeStartHandler = ($event) -> + message = getMessage() + if message and not $window.confirm(message) + $event.stopPropagation() if $event.stopPropagation + $event.preventDefault() if $event.preventDefault + $event.cancelBubble = true + $event.returnValue = false + + # Runs callback functions to retreive most recently added non-empty message. + getMessage = -> + message = null + message = callback() ? message for callback in callbacks + message + + register = (callback) -> + callbacks.push callback + + if $window.addEventListener + $window.addEventListener "beforeunload", onBeforeUnloadHandler + else + $window.onbeforeunload = onBeforeUnloadHandler + + $rootScope.$on "$locationChangeStart", locationChangeStartHandler + + return register: register diff --git a/app/assets/javascripts/admin/utils/utils.js.coffee b/app/assets/javascripts/admin/utils/utils.js.coffee new file mode 100644 index 0000000000..4d58ae930a --- /dev/null +++ b/app/assets/javascripts/admin/utils/utils.js.coffee @@ -0,0 +1 @@ +angular.module("admin.utils", []) \ No newline at end of file From 0d715ce61551b4acc9e54f165d200b5034d4409c Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Fri, 10 Oct 2014 19:36:37 +1100 Subject: [PATCH 05/42] split report permissions --- app/models/spree/ability_decorator.rb | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index 5fdb4c2342..a62eae3935 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -1,6 +1,8 @@ class AbilityDecorator include CanCan::Ability + # All abilites are allocated from this initialiser, currently in 5 chunks. + # Spree also defines other abilities. def initialize(user) add_base_abilities user if is_new_user? user add_enterprise_management_abilities user if can_manage_enterprises? user @@ -9,19 +11,22 @@ class AbilityDecorator add_relationship_management_abilities user if can_manage_relationships? user end - + # New users have no enterprises. def is_new_user?(user) user.enterprises.blank? end + # Users can manage an enterprise if they have one. def can_manage_enterprises?(user) user.enterprises.present? end + # Users can manage products if they have an enterprise. def can_manage_products?(user) can_manage_enterprises? user end + # Users can manage orders if they have a sells own/any enterprise. def can_manage_orders?(user) ( user.enterprises.map(&:type) & %w(single full) ).any? end @@ -30,6 +35,7 @@ class AbilityDecorator can_manage_enterprises? user end + # New users can create an enterprise, and gain other permissions from doing this. def add_base_abilities(user) can [:create], Enterprise end @@ -47,6 +53,12 @@ class AbilityDecorator can [:read, :edit, :update, :bulk_update], Enterprise do |enterprise| user.enterprises.include? enterprise end + + # All enterprises can have fees, though possibly suppliers don't need them? + can [:index, :create], EnterpriseFee + can [:admin, :read, :edit, :bulk_update, :destroy], EnterpriseFee do |enterprise_fee| + user.enterprises.include? enterprise_fee.enterprise + end end def add_product_management_abilities(user) @@ -66,6 +78,9 @@ class AbilityDecorator can [:admin, :index, :read, :search], Spree::Taxon can [:admin, :index, :read, :create, :edit], Spree::Classification + + # Reports page + can [:admin, :index, :customers, :orders_and_fulfillment, :products_and_inventory], :report end def add_order_management_abilities(user) @@ -76,7 +91,7 @@ class AbilityDecorator # during the order creation process from the admin backend order.distributor.nil? || user.enterprises.include?(order.distributor) end - can [:admin, :bulk_management], Spree::Order if user.admin? || user.enterprises.any?(&:is_distributor?) + can [:admin, :bulk_management], Spree::Order if user.admin? || user.enterprises.any?(&:is_distributor) can [:admin, :create], Spree::LineItem can [:admin, :index, :read, :create, :edit, :update, :fire], Spree::Payment @@ -90,11 +105,6 @@ class AbilityDecorator end can [:for_order_cycle], Enterprise - can [:index, :create], EnterpriseFee - can [:admin, :read, :edit, :bulk_update, :destroy], EnterpriseFee do |enterprise_fee| - user.enterprises.include? enterprise_fee.enterprise - end - can [:admin, :index, :read, :create, :edit, :update], ExchangeVariant can [:admin, :index, :read, :create, :edit, :update], Exchange can [:admin, :index, :read, :create, :edit, :update], ExchangeFee @@ -111,7 +121,7 @@ class AbilityDecorator end # Reports page - can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory], :report + can [:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory], :report end From e44fed2ff0cb6d7ea6a8a733caf1a672c94ac9c7 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sun, 12 Oct 2014 14:00:32 +1100 Subject: [PATCH 06/42] add authorization to reports listings on index page --- .../spree/admin/reports_controller_decorator.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 0abfd783b5..c7f5aa363a 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -608,12 +608,10 @@ Spree::Admin::ReportsController.class_eval do :payments => {:name => "Payment Reports", :description => "Reports for Payments"}, :orders_and_fulfillment => {:name => "Orders & Fulfillment Reports", :description => ''}, :customers => {:name => "Customers", :description => 'Customer details'}, - :products_and_inventory => {:name => "Products & Inventory", :description => ''} + :products_and_inventory => {:name => "Products & Inventory", :description => ''}, + :sales_total => { :name => "Sales Total", :description => "Sales Total For All Orders" } } - if spree_current_user.has_spree_role? 'admin' - reports[:sales_total] = { :name => "Sales Total", :description => "Sales Total For All Orders" } - end - reports + reports.select { |action, details| can? action, :report } end def total_units(line_items) From 46df14c0d96290ba928d8d35decec94c22d7936e Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sun, 12 Oct 2014 14:13:52 +1100 Subject: [PATCH 07/42] refator reports controller a little --- .../admin/reports_controller_decorator.rb | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index c7f5aa363a..3a3ca9de48 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -6,24 +6,6 @@ require 'open_food_network/order_grouper' require 'open_food_network/customers_report' Spree::Admin::ReportsController.class_eval do - # Fetches user's distributors, suppliers and order_cycles - before_filter :load_data, only: [:customers, :products_and_inventory] - - # Render a partial for orders and fulfillment description - respond_override :index => { :html => { :success => lambda { - @reports[:orders_and_fulfillment][:description] = - render_to_string(partial: 'orders_and_fulfillment_description', layout: false, locals: {report_types: REPORT_TYPES[:orders_and_fulfillment]}).html_safe - @reports[:products_and_inventory][:description] = - render_to_string(partial: 'products_and_inventory_description', layout: false, locals: {report_types: REPORT_TYPES[:products_and_inventory]}).html_safe - @reports[:customers][:description] = - render_to_string(partial: 'customers_description', layout: false, locals: {report_types: REPORT_TYPES[:customers]}).html_safe - } } } - - # OVERRIDING THIS so we use a method not a constant for available reports - def index - @reports = available_reports - respond_with(@reports) - end REPORT_TYPES = { orders_and_fulfillment: [ @@ -42,6 +24,26 @@ Spree::Admin::ReportsController.class_eval do ] } + # Fetches user's distributors, suppliers and order_cycles + before_filter :load_data, only: [:customers, :products_and_inventory] + + # Render a partial for orders and fulfillment description + respond_override :index => { :html => { :success => lambda { + @reports[:orders_and_fulfillment][:description] = + render_to_string(partial: 'orders_and_fulfillment_description', layout: false, locals: {report_types: REPORT_TYPES[:orders_and_fulfillment]}).html_safe + @reports[:products_and_inventory][:description] = + render_to_string(partial: 'products_and_inventory_description', layout: false, locals: {report_types: REPORT_TYPES[:products_and_inventory]}).html_safe + @reports[:customers][:description] = + render_to_string(partial: 'customers_description', layout: false, locals: {report_types: REPORT_TYPES[:customers]}).html_safe + } } } + + + # Overide spree reports list. + def index + @reports = authorized_reports + respond_with(@reports) + end + # This action is short because we refactored it like bosses def customers @report_types = REPORT_TYPES[:customers] @@ -601,7 +603,7 @@ Spree::Admin::ReportsController.class_eval do @order_cycles = OrderCycle.active_or_complete.accessible_by(spree_current_user).order('orders_close_at DESC') end - def available_reports + def authorized_reports reports = { :orders_and_distributors => {:name => "Orders And Distributors", :description => "Orders with distributor details"}, :bulk_coop => {:name => "Bulk Co-Op", :description => "Reports for Bulk Co-Op orders"}, @@ -611,7 +613,8 @@ Spree::Admin::ReportsController.class_eval do :products_and_inventory => {:name => "Products & Inventory", :description => ''}, :sales_total => { :name => "Sales Total", :description => "Sales Total For All Orders" } } - reports.select { |action, details| can? action, :report } + # Return only reports the user is authorized to view. + reports.select { |action| can? action, :report } end def total_units(line_items) From 1577c01a77300830196eb9115c6907dda2e0b965 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sun, 12 Oct 2014 22:21:59 +1100 Subject: [PATCH 08/42] add reports abilities specs --- spec/models/spree/ability_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 2d2d1cfb01..62e1973e7f 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -151,6 +151,14 @@ module Spree should_not have_ability(:destroy, for: er2) end + it "should be able to read some reports" do + should have_ability([:admin, :index, :customers, :orders_and_fulfillment, :products_and_inventory], for: :reports) + end + + it "should not be able to read other reports" do + should_not have_ability([:sales_total, :group_buys, :bulk_coop, :payments], for: :reports) + end + end context "when is a distributor enterprise user" do @@ -237,6 +245,15 @@ module Spree it "should not be able to destroy enterprise relationships for other enterprises" do should_not have_ability(:destroy, for: er1) end + + it "should be able to read some reports" do + should have_ability([:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory], for: :reports) + end + + it "should not be able to read other reports" do + should_not have_ability([:sales_total], for: :reports) + end + end context 'Order Cycle co-ordinator' do From 9343c3608b8999dd3be8d39883be60564023a96c Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sun, 12 Oct 2014 22:22:35 +1100 Subject: [PATCH 09/42] allow supplier enterprise manager to see bulk coop reports --- app/models/spree/ability_decorator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index a62eae3935..abf4aeac66 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -80,7 +80,7 @@ class AbilityDecorator can [:admin, :index, :read, :create, :edit], Spree::Classification # Reports page - can [:admin, :index, :customers, :orders_and_fulfillment, :products_and_inventory], :report + can [:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory], :report end def add_order_management_abilities(user) From fd7191f476549d187fdef676540b1f7b149f92d4 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Thu, 16 Oct 2014 05:26:38 +1100 Subject: [PATCH 10/42] add missing orders_and_distributors perm --- app/models/spree/ability_decorator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index abf4aeac66..2d4831ec0b 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -121,7 +121,7 @@ class AbilityDecorator end # Reports page - can [:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory], :report + can [:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory], :report end From 245c1eb30582fdd8941e030abe29b51377319ece Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Fri, 17 Oct 2014 07:40:08 +1100 Subject: [PATCH 11/42] use a directive for navigation check to attach it to the page instead of the controller --- .../enterprises/controllers/enterprise_controller.js.coffee | 6 ++---- .../admin/utils/directives/navigation_check.js.coffee | 4 ++++ app/views/admin/enterprises/_ng_form.html.haml | 2 +- app/views/admin/enterprises/index.html.haml | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) create mode 100644 app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee index 6558c789a2..688bf45a99 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee @@ -1,16 +1,14 @@ angular.module("admin.enterprises") - .controller "enterpriseCtrl", ($scope, longDescription, Enterprise, PaymentMethods, ShippingMethods, NavigationCheck) -> + .controller "enterpriseCtrl", ($scope, longDescription, Enterprise, PaymentMethods, ShippingMethods) -> $scope.Enterprise = Enterprise.enterprise $scope.PaymentMethods = PaymentMethods.paymentMethods $scope.ShippingMethods = ShippingMethods.shippingMethods # htmlVariable is used by textAngular wysiwyg for the long descrtiption. $scope.htmlVariable = longDescription # Provide a callback for a warning message displayed when leaving the page. - navigationCallback = -> + $scope.navigationCallback = -> "You are editing an enterprise!" - NavigationCheck.register navigationCallback - for payment_method in $scope.PaymentMethods payment_method.selected = payment_method.id in $scope.Enterprise.payment_method_ids diff --git a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee new file mode 100644 index 0000000000..26964a677d --- /dev/null +++ b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee @@ -0,0 +1,4 @@ +angular.module("admin.utils").directive "navigationCheck", (NavigationCheck)-> + link: ($scope) -> + # Define navigationCallback on the controller. + NavigationCheck.register($scope.navigationCallback) diff --git a/app/views/admin/enterprises/_ng_form.html.haml b/app/views/admin/enterprises/_ng_form.html.haml index 18e9d6ed36..74b4347f16 100644 --- a/app/views/admin/enterprises/_ng_form.html.haml +++ b/app/views/admin/enterprises/_ng_form.html.haml @@ -3,7 +3,7 @@ = admin_inject_payment_methods = admin_inject_shipping_methods -.sixteen.columns.alpha{ ng: { app: 'admin.enterprises', controller: 'enterpriseCtrl' } } +.sixteen.columns.alpha{ ng: { app: 'admin.enterprises', controller: 'enterpriseCtrl' }, "navigation-check" => "" } .eleven.columns.alpha = render 'form', f: f .one.column   diff --git a/app/views/admin/enterprises/index.html.haml b/app/views/admin/enterprises/index.html.haml index 03e5335155..b2a215b1c6 100644 --- a/app/views/admin/enterprises/index.html.haml +++ b/app/views/admin/enterprises/index.html.haml @@ -8,7 +8,7 @@ = render 'admin/shared/enterprises_sub_menu' -= form_for @enterprise_set, :url => main_app.bulk_update_admin_enterprises_path do |f| += form_for @enterprise_set, url: main_app.bulk_update_admin_enterprises_path do |f| %table#listing_enterprises.index %colgroup %col{style: "width: 25%;"}/ From 9536b3e764c7f3a5d82ae91b0c801f71e85d7410 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Fri, 17 Oct 2014 07:58:08 +1100 Subject: [PATCH 12/42] add navigation directive default --- .../admin/utils/directives/navigation_check.js.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee index 26964a677d..7eae3d69cd 100644 --- a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee +++ b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee @@ -1,4 +1,6 @@ angular.module("admin.utils").directive "navigationCheck", (NavigationCheck)-> link: ($scope) -> - # Define navigationCallback on the controller. + # Define navigationCallback on a controller in $scope, otherwise this default will be used: + $scope.navigationCallback ||= -> + "You will lose any unsaved work!" NavigationCheck.register($scope.navigationCallback) From 694dd0c32934702011dc3253545fee805e4ec573 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 17 Oct 2014 10:52:36 +1100 Subject: [PATCH 13/42] Enterprise user selling own produce only sees simple order cycle listing --- app/helpers/order_cycles_helper.rb | 4 ++++ app/views/admin/order_cycles/_row.html.haml | 20 +++++++++++--------- app/views/admin/order_cycles/index.html.haml | 14 ++++++++------ lib/open_food_network/permissions.rb | 6 ++++++ spec/features/admin/order_cycles_spec.rb | 20 ++++++++++++++++++++ 5 files changed, 49 insertions(+), 15 deletions(-) diff --git a/app/helpers/order_cycles_helper.rb b/app/helpers/order_cycles_helper.rb index dfd957a143..23ac74e944 100644 --- a/app/helpers/order_cycles_helper.rb +++ b/app/helpers/order_cycles_helper.rb @@ -62,6 +62,10 @@ module OrderCyclesHelper OrderCycle.active.with_distributor(@distributor).present? end + def order_cycles_simple_view + !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles? + end + def order_cycles_enabled? OpenFoodNetwork::FeatureToggle.enabled? :order_cycles end diff --git a/app/views/admin/order_cycles/_row.html.haml b/app/views/admin/order_cycles/_row.html.haml index 75e84de025..e95adff38f 100644 --- a/app/views/admin/order_cycles/_row.html.haml +++ b/app/views/admin/order_cycles/_row.html.haml @@ -4,15 +4,17 @@ %td= link_to order_cycle.name, main_app.edit_admin_order_cycle_path(order_cycle) %td= order_cycle_form.text_field :orders_open_at, :class => 'datetimepicker', :value => order_cycle.orders_open_at %td= order_cycle_form.text_field :orders_close_at, :class => 'datetimepicker', :value => order_cycle.orders_close_at - %td.suppliers - - order_cycle.suppliers.managed_by(spree_current_user).each do |s| - = s.name - %br/ - %td= order_cycle.coordinator.name - %td.distributors - - order_cycle.distributors.managed_by(spree_current_user).each do |d| - = d.name - %br/ + + - unless order_cycles_simple_view + %td.suppliers + - order_cycle.suppliers.managed_by(spree_current_user).each do |s| + = s.name + %br/ + %td= order_cycle.coordinator.name + %td.distributors + - order_cycle.distributors.managed_by(spree_current_user).each do |d| + = d.name + %br/ %td.products - variant_images = capture do diff --git a/app/views/admin/order_cycles/index.html.haml b/app/views/admin/order_cycles/index.html.haml index 1fac06f507..f649a4ab47 100644 --- a/app/views/admin/order_cycles/index.html.haml +++ b/app/views/admin/order_cycles/index.html.haml @@ -13,9 +13,10 @@ %col %col{'style' => 'width: 20%;'} %col{'style' => 'width: 20%;'} - %col - %col - %col + - unless order_cycles_simple_view + %col + %col + %col %col %col %col @@ -25,9 +26,10 @@ %th Name %th Open %th Close - %th Suppliers - %th Coordinator - %th Distributors + - unless order_cycles_simple_view + %th Suppliers + %th Coordinator + %th Distributors %th Products %th.actions %th.actions diff --git a/lib/open_food_network/permissions.rb b/lib/open_food_network/permissions.rb index 3d5df1e804..678e70941a 100644 --- a/lib/open_food_network/permissions.rb +++ b/lib/open_food_network/permissions.rb @@ -4,6 +4,12 @@ module OpenFoodNetwork @user = user end + def can_manage_complex_order_cycles? + managed_and_related_enterprises_with(:add_to_order_cycle).any? do |e| + e.sells == 'any' + end + end + # Find enterprises that an admin is allowed to add to an order cycle def order_cycle_enterprises managed_and_related_enterprises_with :add_to_order_cycle diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index febd966109..354be34671 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -572,7 +572,27 @@ feature %q{ occ = OrderCycle.last occ.name.should == "COPY OF #{oc.name}" end + end + + describe "as an enterprise user selling only my own produce" do + let(:user) { create_enterprise_user } + let(:enterprise) { create(:enterprise, is_primary_producer: true, sells: 'own') } + + use_short_wait + + before do + user.enterprise_roles.create! enterprise: enterprise + login_to_admin_as user + end + + it "shows me an index of order cycles without enterprise columns" do + create(:order_cycle, coordinator: enterprise) + visit admin_order_cycles_path + page.should_not have_selector 'th', text: 'SUPPLIERS' + page.should_not have_selector 'th', text: 'COORDINATOR' + page.should_not have_selector 'th', text: 'DISTRIBUTORS' + end end From f060da9c8db88368b41c144ba7753dd019223a91 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 17 Oct 2014 14:13:27 +1100 Subject: [PATCH 14/42] Rename angular app order_cycle -> admin.order_cycles --- app/assets/javascripts/admin/order_cycle.js.erb.coffee | 2 +- app/views/admin/order_cycles/edit.html.haml | 2 +- app/views/admin/order_cycles/new.html.haml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/admin/order_cycle.js.erb.coffee b/app/assets/javascripts/admin/order_cycle.js.erb.coffee index 64f2550466..bcfb338a15 100644 --- a/app/assets/javascripts/admin/order_cycle.js.erb.coffee +++ b/app/assets/javascripts/admin/order_cycle.js.erb.coffee @@ -1,4 +1,4 @@ -angular.module('order_cycle', ['ngResource']) +angular.module('admin.order_cycles', ['ngResource']) .controller('AdminCreateOrderCycleCtrl', ['$scope', 'OrderCycle', 'Enterprise', 'EnterpriseFee', ($scope, OrderCycle, Enterprise, EnterpriseFee) -> $scope.enterprises = Enterprise.index() $scope.supplied_products = Enterprise.supplied_products diff --git a/app/views/admin/order_cycles/edit.html.haml b/app/views/admin/order_cycles/edit.html.haml index 9bf0a8ca31..b22f0cf51d 100644 --- a/app/views/admin/order_cycles/edit.html.haml +++ b/app/views/admin/order_cycles/edit.html.haml @@ -1,4 +1,4 @@ %h1 Edit Order Cycle -= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'order_cycle', 'ng-controller' => 'AdminEditOrderCycleCtrl', 'ng-submit' => 'submit()'} do |f| += form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.order_cycles', 'ng-controller' => 'AdminEditOrderCycleCtrl', 'ng-submit' => 'submit()'} do |f| = render 'form', :f => f diff --git a/app/views/admin/order_cycles/new.html.haml b/app/views/admin/order_cycles/new.html.haml index c2e9c924f2..de1f229258 100644 --- a/app/views/admin/order_cycles/new.html.haml +++ b/app/views/admin/order_cycles/new.html.haml @@ -1,4 +1,4 @@ %h1 New Order Cycle -= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'order_cycle', 'ng-controller' => 'AdminCreateOrderCycleCtrl', 'ng-submit' => 'submit()'} do |f| += form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.order_cycles', 'ng-controller' => 'AdminCreateOrderCycleCtrl', 'ng-submit' => 'submit()'} do |f| = render 'form', :f => f From 078d2bac118be128429b94396ce88e1376ebb68a Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 17 Oct 2014 16:50:16 +1100 Subject: [PATCH 15/42] Extract factories from order cycles admin angular --- .../admin/order_cycle.js.erb.coffee | 229 ------------------ .../services/enterprise.js.coffee | 43 ++++ .../services/enterprise_fee.js.coffee | 18 ++ .../services/order_cycle.js.coffee | 168 +++++++++++++ 4 files changed, 229 insertions(+), 229 deletions(-) create mode 100644 app/assets/javascripts/admin/order_cycles/services/enterprise.js.coffee create mode 100644 app/assets/javascripts/admin/order_cycles/services/enterprise_fee.js.coffee create mode 100644 app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee diff --git a/app/assets/javascripts/admin/order_cycle.js.erb.coffee b/app/assets/javascripts/admin/order_cycle.js.erb.coffee index bcfb338a15..6a7d565bae 100644 --- a/app/assets/javascripts/admin/order_cycle.js.erb.coffee +++ b/app/assets/javascripts/admin/order_cycle.js.erb.coffee @@ -162,235 +162,6 @@ angular.module('admin.order_cycles', ['ngResource']) $httpProvider.defaults.headers.common['X-CSRF-Token'] = $('meta[name=csrf-token]').attr('content') ]) - .factory('OrderCycle', ['$resource', '$window', ($resource, $window) -> - OrderCycle = $resource '/admin/order_cycles/:order_cycle_id.json', {}, { - 'index': { method: 'GET', isArray: true} - 'create': { method: 'POST'} - 'update': { method: 'PUT'}} - - { - order_cycle: - incoming_exchanges: [] - outgoing_exchanges: [] - coordinator_fees: [] - - loaded: false - - exchangeSelectedVariants: (exchange) -> - numActiveVariants = 0 - numActiveVariants++ for id, active of exchange.variants when active - numActiveVariants - - exchangeDirection: (exchange) -> - if this.order_cycle.incoming_exchanges.indexOf(exchange) == -1 then 'outgoing' else 'incoming' - - toggleProducts: (exchange) -> - exchange.showProducts = !exchange.showProducts - - setExchangeVariants: (exchange, variants, selected) -> - exchange.variants[variant] = selected for variant in variants - - addSupplier: (new_supplier_id) -> - this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []}) - - addDistributor: (new_distributor_id) -> - this.order_cycle.outgoing_exchanges.push({enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: []}) - - removeExchange: (exchange) -> - if exchange.incoming - incoming_index = this.order_cycle.incoming_exchanges.indexOf exchange - this.order_cycle.incoming_exchanges.splice(incoming_index, 1) - this.removeDistributionOfVariant(variant_id) for variant_id, active of exchange.variants when active - else - outgoing_index = this.order_cycle.outgoing_exchanges.indexOf exchange - this.order_cycle.outgoing_exchanges.splice(outgoing_index, 1) if outgoing_index > -1 - - addCoordinatorFee: -> - this.order_cycle.coordinator_fees.push({}) - - removeCoordinatorFee: (index) -> - this.order_cycle.coordinator_fees.splice(index, 1) - - addExchangeFee: (exchange) -> - exchange.enterprise_fees.push({}) - - removeExchangeFee: (exchange, index) -> - exchange.enterprise_fees.splice(index, 1) - - productSuppliedToOrderCycle: (product) -> - product_variant_ids = (variant.id for variant in product.variants) - variant_ids = [product.master_id].concat(product_variant_ids) - incomingExchangesVariants = this.incomingExchangesVariants() - - # TODO: This is an O(n^2) implementation of set intersection and thus is slooow. - # Use a better algorithm if needed. - # Also, incomingExchangesVariants is called every time, when it only needs to be - # called once per change to incoming variants. Some sort of caching? - ids = (variant_id for variant_id in variant_ids when incomingExchangesVariants.indexOf(variant_id) != -1) - ids.length > 0 - - variantSuppliedToOrderCycle: (variant) -> - this.incomingExchangesVariants().indexOf(variant.id) != -1 - - incomingExchangesVariants: -> - variant_ids = [] - - for exchange in this.order_cycle.incoming_exchanges - variant_ids.push(parseInt(id)) for id, active of exchange.variants when active - variant_ids - - participatingEnterpriseIds: -> - suppliers = (exchange.enterprise_id for exchange in this.order_cycle.incoming_exchanges) - distributors = (exchange.enterprise_id for exchange in this.order_cycle.outgoing_exchanges) - jQuery.unique(suppliers.concat(distributors)).sort() - - removeDistributionOfVariant: (variant_id) -> - for exchange in this.order_cycle.outgoing_exchanges - exchange.variants[variant_id] = false - - load: (order_cycle_id) -> - service = this - OrderCycle.get {order_cycle_id: order_cycle_id}, (oc) -> - angular.extend(service.order_cycle, oc) - service.order_cycle.incoming_exchanges = [] - service.order_cycle.outgoing_exchanges = [] - for exchange in service.order_cycle.exchanges - if exchange.incoming - angular.extend(exchange, {enterprise_id: exchange.sender_id, active: true}) - delete(exchange.receiver_id) - service.order_cycle.incoming_exchanges.push(exchange) - - else - angular.extend(exchange, {enterprise_id: exchange.receiver_id, active: true}) - delete(exchange.sender_id) - service.order_cycle.outgoing_exchanges.push(exchange) - - delete(service.order_cycle.exchanges) - service.loaded = true - - this.order_cycle - - create: -> - oc = new OrderCycle({order_cycle: this.dataForSubmit()}) - oc.$create (data) -> - if data['success'] - $window.location = '/admin/order_cycles' - else - console.log('Failed to create order cycle') - - update: -> - oc = new OrderCycle({order_cycle: this.dataForSubmit()}) - oc.$update {order_cycle_id: this.order_cycle.id}, (data) -> - if data['success'] - $window.location = '/admin/order_cycles' - else - console.log('Failed to update order cycle') - - dataForSubmit: -> - data = this.deepCopy() - data = this.removeInactiveExchanges(data) - data = this.translateCoordinatorFees(data) - data = this.translateExchangeFees(data) - data - - deepCopy: -> - data = angular.extend({}, this.order_cycle) - - # Copy exchanges - data.incoming_exchanges = (angular.extend {}, exchange for exchange in this.order_cycle.incoming_exchanges) if this.order_cycle.incoming_exchanges? - data.outgoing_exchanges = (angular.extend {}, exchange for exchange in this.order_cycle.outgoing_exchanges) if this.order_cycle.outgoing_exchanges? - - # Copy exchange fees - all_exchanges = (data.incoming_exchanges || []) + (data.outgoing_exchanges || []) - for exchange in all_exchanges - if exchange.enterprise_fees? - exchange.enterprise_fees = (angular.extend {}, fee for fee in exchange.enterprise_fees) - - data - - removeInactiveExchanges: (order_cycle) -> - order_cycle.incoming_exchanges = - (exchange for exchange in order_cycle.incoming_exchanges when exchange.active) - order_cycle.outgoing_exchanges = - (exchange for exchange in order_cycle.outgoing_exchanges when exchange.active) - order_cycle - - translateCoordinatorFees: (order_cycle) -> - order_cycle.coordinator_fee_ids = (fee.id for fee in order_cycle.coordinator_fees) - delete order_cycle.coordinator_fees - order_cycle - - translateExchangeFees: (order_cycle) -> - for exchange in order_cycle.incoming_exchanges - exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees) - delete exchange.enterprise_fees - for exchange in order_cycle.outgoing_exchanges - exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees) - delete exchange.enterprise_fees - order_cycle - }]) - - .factory('Enterprise', ['$resource', ($resource) -> - Enterprise = $resource('/admin/enterprises/for_order_cycle/:enterprise_id.json', {}, {'index': {method: 'GET', isArray: true}}) - - { - Enterprise: Enterprise - enterprises: {} - supplied_products: [] - loaded: false - - index: -> - service = this - - Enterprise.index (data) -> - for enterprise in data - service.enterprises[enterprise.id] = enterprise - - for product in enterprise.supplied_products - service.supplied_products.push(product) - - service.loaded = true - - this.enterprises - - suppliedVariants: (enterprise_id) -> - vs = (this.variantsOf(product) for product in this.enterprises[enterprise_id].supplied_products) - [].concat vs... - - variantsOf: (product) -> - if product.variants.length > 0 - variant.id for variant in product.variants - else - [product.master_id] - - totalVariants: (enterprise) -> - numVariants = 0 - - if enterprise - counts = for product in enterprise.supplied_products - numVariants += if product.variants.length == 0 then 1 else product.variants.length - - numVariants - }]) - - .factory('EnterpriseFee', ['$resource', ($resource) -> - EnterpriseFee = $resource('/admin/enterprise_fees/:enterprise_fee_id.json', {}, {'index': {method: 'GET', isArray: true}}) - - { - EnterpriseFee: EnterpriseFee - enterprise_fees: {} - loaded: false - - index: -> - service = this - EnterpriseFee.index (data) -> - service.enterprise_fees = data - service.loaded = true - - forEnterprise: (enterprise_id) -> - enterprise_fee for enterprise_fee in this.enterprise_fees when enterprise_fee.enterprise_id == enterprise_id - }]) - .directive('datetimepicker', ['$parse', ($parse) -> (scope, element, attrs) -> # using $parse instead of scope[attrs.datetimepicker] for cases diff --git a/app/assets/javascripts/admin/order_cycles/services/enterprise.js.coffee b/app/assets/javascripts/admin/order_cycles/services/enterprise.js.coffee new file mode 100644 index 0000000000..244d050aba --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/services/enterprise.js.coffee @@ -0,0 +1,43 @@ +angular.module('admin.order_cycles').factory('Enterprise', ($resource) -> + Enterprise = $resource('/admin/enterprises/for_order_cycle/:enterprise_id.json', {}, {'index': {method: 'GET', isArray: true}}) + + { + Enterprise: Enterprise + enterprises: {} + supplied_products: [] + loaded: false + + index: (callback=null) -> + service = this + + Enterprise.index (data) -> + for enterprise in data + service.enterprises[enterprise.id] = enterprise + + for product in enterprise.supplied_products + service.supplied_products.push(product) + + service.loaded = true + (callback || angular.noop)(service.enterprises) + + this.enterprises + + suppliedVariants: (enterprise_id) -> + vs = (this.variantsOf(product) for product in this.enterprises[enterprise_id].supplied_products) + [].concat vs... + + variantsOf: (product) -> + if product.variants.length > 0 + variant.id for variant in product.variants + else + [product.master_id] + + totalVariants: (enterprise) -> + numVariants = 0 + + if enterprise + counts = for product in enterprise.supplied_products + numVariants += if product.variants.length == 0 then 1 else product.variants.length + + numVariants + }) \ No newline at end of file diff --git a/app/assets/javascripts/admin/order_cycles/services/enterprise_fee.js.coffee b/app/assets/javascripts/admin/order_cycles/services/enterprise_fee.js.coffee new file mode 100644 index 0000000000..330d7c031e --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/services/enterprise_fee.js.coffee @@ -0,0 +1,18 @@ +angular.module('admin.order_cycles').factory('EnterpriseFee', ($resource) -> + EnterpriseFee = $resource('/admin/enterprise_fees/:enterprise_fee_id.json', {}, {'index': {method: 'GET', isArray: true}}) + + { + EnterpriseFee: EnterpriseFee + enterprise_fees: {} + loaded: false + + index: -> + service = this + EnterpriseFee.index (data) -> + service.enterprise_fees = data + service.loaded = true + + forEnterprise: (enterprise_id) -> + enterprise_fee for enterprise_fee in this.enterprise_fees when enterprise_fee.enterprise_id == enterprise_id + }) + diff --git a/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee b/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee new file mode 100644 index 0000000000..5e46fdda50 --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee @@ -0,0 +1,168 @@ +angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window) -> + OrderCycle = $resource '/admin/order_cycles/:order_cycle_id.json', {}, { + 'index': { method: 'GET', isArray: true} + 'create': { method: 'POST'} + 'update': { method: 'PUT'}} + + { + order_cycle: + incoming_exchanges: [] + outgoing_exchanges: [] + coordinator_fees: [] + + loaded: false + + exchangeSelectedVariants: (exchange) -> + numActiveVariants = 0 + numActiveVariants++ for id, active of exchange.variants when active + numActiveVariants + + exchangeDirection: (exchange) -> + if this.order_cycle.incoming_exchanges.indexOf(exchange) == -1 then 'outgoing' else 'incoming' + + toggleProducts: (exchange) -> + exchange.showProducts = !exchange.showProducts + + setExchangeVariants: (exchange, variants, selected) -> + exchange.variants[variant] = selected for variant in variants + + addSupplier: (new_supplier_id) -> + this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []}) + + addDistributor: (new_distributor_id) -> + this.order_cycle.outgoing_exchanges.push({enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: []}) + + removeExchange: (exchange) -> + if exchange.incoming + incoming_index = this.order_cycle.incoming_exchanges.indexOf exchange + this.order_cycle.incoming_exchanges.splice(incoming_index, 1) + this.removeDistributionOfVariant(variant_id) for variant_id, active of exchange.variants when active + else + outgoing_index = this.order_cycle.outgoing_exchanges.indexOf exchange + this.order_cycle.outgoing_exchanges.splice(outgoing_index, 1) if outgoing_index > -1 + + addCoordinatorFee: -> + this.order_cycle.coordinator_fees.push({}) + + removeCoordinatorFee: (index) -> + this.order_cycle.coordinator_fees.splice(index, 1) + + addExchangeFee: (exchange) -> + exchange.enterprise_fees.push({}) + + removeExchangeFee: (exchange, index) -> + exchange.enterprise_fees.splice(index, 1) + + productSuppliedToOrderCycle: (product) -> + product_variant_ids = (variant.id for variant in product.variants) + variant_ids = [product.master_id].concat(product_variant_ids) + incomingExchangesVariants = this.incomingExchangesVariants() + + # TODO: This is an O(n^2) implementation of set intersection and thus is slooow. + # Use a better algorithm if needed. + # Also, incomingExchangesVariants is called every time, when it only needs to be + # called once per change to incoming variants. Some sort of caching? + ids = (variant_id for variant_id in variant_ids when incomingExchangesVariants.indexOf(variant_id) != -1) + ids.length > 0 + + variantSuppliedToOrderCycle: (variant) -> + this.incomingExchangesVariants().indexOf(variant.id) != -1 + + incomingExchangesVariants: -> + variant_ids = [] + + for exchange in this.order_cycle.incoming_exchanges + variant_ids.push(parseInt(id)) for id, active of exchange.variants when active + variant_ids + + participatingEnterpriseIds: -> + suppliers = (exchange.enterprise_id for exchange in this.order_cycle.incoming_exchanges) + distributors = (exchange.enterprise_id for exchange in this.order_cycle.outgoing_exchanges) + jQuery.unique(suppliers.concat(distributors)).sort() + + removeDistributionOfVariant: (variant_id) -> + for exchange in this.order_cycle.outgoing_exchanges + exchange.variants[variant_id] = false + + load: (order_cycle_id) -> + service = this + OrderCycle.get {order_cycle_id: order_cycle_id}, (oc) -> + angular.extend(service.order_cycle, oc) + service.order_cycle.incoming_exchanges = [] + service.order_cycle.outgoing_exchanges = [] + for exchange in service.order_cycle.exchanges + if exchange.incoming + angular.extend(exchange, {enterprise_id: exchange.sender_id, active: true}) + delete(exchange.receiver_id) + service.order_cycle.incoming_exchanges.push(exchange) + + else + angular.extend(exchange, {enterprise_id: exchange.receiver_id, active: true}) + delete(exchange.sender_id) + service.order_cycle.outgoing_exchanges.push(exchange) + + delete(service.order_cycle.exchanges) + service.loaded = true + + this.order_cycle + + create: -> + oc = new OrderCycle({order_cycle: this.dataForSubmit()}) + oc.$create (data) -> + if data['success'] + $window.location = '/admin/order_cycles' + else + console.log('Failed to create order cycle') + + update: -> + oc = new OrderCycle({order_cycle: this.dataForSubmit()}) + oc.$update {order_cycle_id: this.order_cycle.id}, (data) -> + if data['success'] + $window.location = '/admin/order_cycles' + else + console.log('Failed to update order cycle') + + dataForSubmit: -> + data = this.deepCopy() + data = this.removeInactiveExchanges(data) + data = this.translateCoordinatorFees(data) + data = this.translateExchangeFees(data) + data + + deepCopy: -> + data = angular.extend({}, this.order_cycle) + + # Copy exchanges + data.incoming_exchanges = (angular.extend {}, exchange for exchange in this.order_cycle.incoming_exchanges) if this.order_cycle.incoming_exchanges? + data.outgoing_exchanges = (angular.extend {}, exchange for exchange in this.order_cycle.outgoing_exchanges) if this.order_cycle.outgoing_exchanges? + + # Copy exchange fees + all_exchanges = (data.incoming_exchanges || []) + (data.outgoing_exchanges || []) + for exchange in all_exchanges + if exchange.enterprise_fees? + exchange.enterprise_fees = (angular.extend {}, fee for fee in exchange.enterprise_fees) + + data + + removeInactiveExchanges: (order_cycle) -> + order_cycle.incoming_exchanges = + (exchange for exchange in order_cycle.incoming_exchanges when exchange.active) + order_cycle.outgoing_exchanges = + (exchange for exchange in order_cycle.outgoing_exchanges when exchange.active) + order_cycle + + translateCoordinatorFees: (order_cycle) -> + order_cycle.coordinator_fee_ids = (fee.id for fee in order_cycle.coordinator_fees) + delete order_cycle.coordinator_fees + order_cycle + + translateExchangeFees: (order_cycle) -> + for exchange in order_cycle.incoming_exchanges + exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees) + delete exchange.enterprise_fees + for exchange in order_cycle.outgoing_exchanges + exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees) + delete exchange.enterprise_fees + order_cycle + }) + From d8b648d531ff811870bd5802ee70475795f081b2 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 17 Oct 2014 16:51:03 +1100 Subject: [PATCH 16/42] Extract name and timing form from order cycles --- app/views/admin/order_cycles/_form.html.haml | 12 +----------- .../order_cycles/_name_and_timing_form.html.haml | 11 +++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 app/views/admin/order_cycles/_name_and_timing_form.html.haml diff --git a/app/views/admin/order_cycles/_form.html.haml b/app/views/admin/order_cycles/_form.html.haml index e859374a3b..82146fabdd 100644 --- a/app/views/admin/order_cycles/_form.html.haml +++ b/app/views/admin/order_cycles/_form.html.haml @@ -1,14 +1,4 @@ -= f.label :name -= f.text_field :name, 'ng-model' => 'order_cycle.name', 'required' => true -%br/ - -.date-field - = f.label :orders_open_at, 'Orders open' - = f.text_field :orders_open_at, 'datetimepicker' => 'order_cycle.orders_open_at', 'ng-model' => 'order_cycle.orders_open_at' -.date-field - = f.label :orders_close_at, 'Orders close' - = f.text_field :orders_close_at, 'datetimepicker' => 'order_cycle.orders_close_at', 'ng-model' => 'order_cycle.orders_close_at' -%br/ += render 'name_and_timing_form', f: f %h2 Incoming diff --git a/app/views/admin/order_cycles/_name_and_timing_form.html.haml b/app/views/admin/order_cycles/_name_and_timing_form.html.haml new file mode 100644 index 0000000000..437a6a44f7 --- /dev/null +++ b/app/views/admin/order_cycles/_name_and_timing_form.html.haml @@ -0,0 +1,11 @@ += f.label :name += f.text_field :name, 'ng-model' => 'order_cycle.name', 'required' => true +%br/ + +.date-field + = f.label :orders_open_at, 'Orders open' + = f.text_field :orders_open_at, 'datetimepicker' => 'order_cycle.orders_open_at', 'ng-model' => 'order_cycle.orders_open_at' +.date-field + = f.label :orders_close_at, 'Orders close' + = f.text_field :orders_close_at, 'datetimepicker' => 'order_cycle.orders_close_at', 'ng-model' => 'order_cycle.orders_close_at' +%br/ From deedafde9ac13b609c0d4b08852e27a89fcd1a09 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 17 Oct 2014 16:55:55 +1100 Subject: [PATCH 17/42] WIP: Simple order cycle form loads and displays correct info --- .../order_cycles/controllers/simple.js.coffee | 27 ++++++++ app/helpers/order_cycles_helper.rb | 2 +- .../admin/order_cycles/_simple_form.html.haml | 18 ++++++ app/views/admin/order_cycles/new.html.haml | 9 ++- spec/features/admin/order_cycles_spec.rb | 64 +++++++++++++++++-- 5 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee create mode 100644 app/views/admin/order_cycles/_simple_form.html.haml diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee new file mode 100644 index 0000000000..cdc8947f25 --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee @@ -0,0 +1,27 @@ +angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, OrderCycle, Enterprise, EnterpriseFee) -> + $scope.enterprises = Enterprise.index (enterprises) => + enterprise = enterprises[Object.keys(enterprises)[0]] + OrderCycle.addSupplier enterprise.id + OrderCycle.addDistributor enterprise.id + + OrderCycle.setExchangeVariants(OrderCycle.order_cycle.incoming_exchanges[0], + Enterprise.suppliedVariants(enterprise.id), true) + + OrderCycle.order_cycle.coordinator_id = enterprise.id + + $scope.enterprise_fees = EnterpriseFee.index() + + $scope.order_cycle = OrderCycle.order_cycle + + $scope.loaded = -> + Enterprise.loaded && EnterpriseFee.loaded + + $scope.removeDistributionOfVariant = angular.noop + + $scope.addCoordinatorFee = ($event) -> + $event.preventDefault() + OrderCycle.addCoordinatorFee() + + $scope.enterpriseFeesForEnterprise = (enterprise_id) -> + EnterpriseFee.forEnterprise(parseInt(enterprise_id)) + diff --git a/app/helpers/order_cycles_helper.rb b/app/helpers/order_cycles_helper.rb index 23ac74e944..627d117368 100644 --- a/app/helpers/order_cycles_helper.rb +++ b/app/helpers/order_cycles_helper.rb @@ -63,7 +63,7 @@ module OrderCyclesHelper end def order_cycles_simple_view - !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles? + @order_cycles_simple_view ||= !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles? end def order_cycles_enabled? diff --git a/app/views/admin/order_cycles/_simple_form.html.haml b/app/views/admin/order_cycles/_simple_form.html.haml new file mode 100644 index 0000000000..37f7ab0152 --- /dev/null +++ b/app/views/admin/order_cycles/_simple_form.html.haml @@ -0,0 +1,18 @@ += render 'name_and_timing_form', f: f + += text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => 'Ready for (ie. Date / Time)', 'ng-model' => 'outgoing_exchange.pickup_time' +%br/ += text_field_tag 'order_cycle_outgoing_exchange_0_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_instructions', 'placeholder' => 'Pick-up instructions', 'ng-model' => 'outgoing_exchange.pickup_instructions' + +%div{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}} + = render 'exchange_supplied_products_form' + += render 'coordinator_fees', f: f + +.actions + = f.submit @order_cycle.new_record? ? 'Create' : 'Update', 'ng-disabled' => '!loaded()' + %span{'ng-show' => 'loaded()'} + or + = link_to 'Cancel', main_app.admin_order_cycles_path + %span{'ng-hide' => 'loaded()'} Loading... + diff --git a/app/views/admin/order_cycles/new.html.haml b/app/views/admin/order_cycles/new.html.haml index de1f229258..716e537874 100644 --- a/app/views/admin/order_cycles/new.html.haml +++ b/app/views/admin/order_cycles/new.html.haml @@ -1,4 +1,9 @@ %h1 New Order Cycle -= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.order_cycles', 'ng-controller' => 'AdminCreateOrderCycleCtrl', 'ng-submit' => 'submit()'} do |f| - = render 'form', :f => f +- ng_controller = order_cycles_simple_view ? 'AdminSimpleCreateOrderCycleCtrl' : 'AdminCreateOrderCycleCtrl' + += form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.order_cycles', 'ng-controller' => ng_controller, 'ng-submit' => 'submit()'} do |f| + - if order_cycles_simple_view + = render 'simple_form', f: f + - else + = render 'form', f: f diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 354be34671..c579b75f7c 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -131,16 +131,16 @@ feature %q{ page.should have_selector 'td.distributors', text: 'My distributor' # And it should have some fees - OrderCycle.last.exchanges.incoming.first.enterprise_fees.should == [supplier_fee] - OrderCycle.last.coordinator_fees.should == [coordinator_fee] - OrderCycle.last.exchanges.outgoing.first.enterprise_fees.should == [distributor_fee] + oc = OrderCycle.last + oc.exchanges.incoming.first.enterprise_fees.should == [supplier_fee] + oc.coordinator_fees.should == [coordinator_fee] + oc.exchanges.outgoing.first.enterprise_fees.should == [distributor_fee] # And it should have some variants selected - OrderCycle.last.exchanges.first.variants.count.should == 2 - OrderCycle.last.exchanges.last.variants.count.should == 2 + oc.exchanges.first.variants.count.should == 2 + oc.exchanges.last.variants.count.should == 2 # And my pickup time and instructions should have been saved - oc = OrderCycle.last exchange = oc.exchanges.where(:sender_id => oc.coordinator_id).first exchange.pickup_time.should == 'pickup time' exchange.pickup_instructions.should == 'pickup instructions' @@ -575,9 +575,14 @@ feature %q{ end - describe "as an enterprise user selling only my own produce" do + describe "simplified interface for enterprise users selling only their own produce" do let(:user) { create_enterprise_user } let(:enterprise) { create(:enterprise, is_primary_producer: true, sells: 'own') } + let!(:p1) { create(:simple_product, supplier: enterprise) } + let!(:p2) { create(:simple_product, supplier: enterprise) } + let!(:p3) { create(:simple_product, supplier: enterprise) } + let!(:v) { create(:variant, product: p3) } + let!(:fee) { create(:enterprise_fee, enterprise: enterprise, name: 'Coord fee') } use_short_wait @@ -593,6 +598,51 @@ feature %q{ page.should_not have_selector 'th', text: 'COORDINATOR' page.should_not have_selector 'th', text: 'DISTRIBUTORS' end + + it "creates order cycles", js: true do + # When I go to the new order cycle page + visit admin_order_cycles_path + click_link 'New Order Cycle' + + # And I fill in the basic fields + fill_in 'order_cycle_name', with: 'Plums & Avos' + fill_in 'order_cycle_orders_open_at', with: '2014-10-17 06:00:00' + fill_in 'order_cycle_orders_close_at', with: '2014-10-24 17:00:00' + fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time' + fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions' + + # Then my products / variants should already be selected + page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p1.master.id}" + page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p2.master.id}" + page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v.id}" + + # When I unselect a product + uncheck "order_cycle_incoming_exchange_0_variants_#{p2.master.id}" + + # And I add a fee and save + click_button 'Add coordinator fee' + select 'Coord fee', from: 'order_cycle_coordinator_fee_0_id' + click_button 'Create' + + # Then my order cycle should have been created + page.should have_content 'Your order cycle has been created.' + page.should have_selector 'a', text: 'Plums & Avos' + page.should have_selector "input[value='2012-11-06 06:00:00 +1100']" + page.should have_selector "input[value='2012-11-13 17:00:00 +1100']" + + # And it should have some variants selected + oc = OrderCycle.last + oc.exchanges.incoming.first.variants.count.should == 2 + oc.exchanges.outgoing.first.variants.count.should == 2 + + # And it should have the fee + oc.coordinator_fees.should == [fee] + + # And my pickup time and instructions should have been saved + ex = oc.exchanges.outgoing.first + ex.pickup_time.should == 'pickup time' + ex.pickup_instructions.should == 'pickup instructions' + end end From 577cb06371632251bbaabfb237eb5f4c4f95b938 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 18 Oct 2014 01:42:29 +1100 Subject: [PATCH 18/42] make navCallback actually versatile --- .../controllers/enterprise_controller.js.coffee | 2 +- .../admin/utils/directives/navigation_check.js.coffee | 11 +++++++---- app/views/admin/enterprises/_ng_form.html.haml | 2 +- app/views/admin/order_cycles/index.html.haml | 2 -- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee index 688bf45a99..0fa452a8d6 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee @@ -6,7 +6,7 @@ angular.module("admin.enterprises") # htmlVariable is used by textAngular wysiwyg for the long descrtiption. $scope.htmlVariable = longDescription # Provide a callback for a warning message displayed when leaving the page. - $scope.navigationCallback = -> + $scope.enterpriseNavCallback = -> "You are editing an enterprise!" for payment_method in $scope.PaymentMethods diff --git a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee index 7eae3d69cd..6f5128d7bf 100644 --- a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee +++ b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee @@ -1,6 +1,9 @@ -angular.module("admin.utils").directive "navigationCheck", (NavigationCheck)-> - link: ($scope) -> +angular.module("admin.utils").directive "navCheck", (NavigationCheck)-> + restrict: 'A' + scope: + navCallback: '&' + link: (scope,element,attributes) -> # Define navigationCallback on a controller in $scope, otherwise this default will be used: - $scope.navigationCallback ||= -> + scope.navCallback ||= -> "You will lose any unsaved work!" - NavigationCheck.register($scope.navigationCallback) + NavigationCheck.register(scope.navCallback) diff --git a/app/views/admin/enterprises/_ng_form.html.haml b/app/views/admin/enterprises/_ng_form.html.haml index 74b4347f16..e3ebe95877 100644 --- a/app/views/admin/enterprises/_ng_form.html.haml +++ b/app/views/admin/enterprises/_ng_form.html.haml @@ -3,7 +3,7 @@ = admin_inject_payment_methods = admin_inject_shipping_methods -.sixteen.columns.alpha{ ng: { app: 'admin.enterprises', controller: 'enterpriseCtrl' }, "navigation-check" => "" } +.sixteen.columns.alpha{ ng: { app: 'admin.enterprises', controller: 'enterpriseCtrl' }, nav: { check: '', callback: 'enterpriseNavCallback()' }} .eleven.columns.alpha = render 'form', f: f .one.column   diff --git a/app/views/admin/order_cycles/index.html.haml b/app/views/admin/order_cycles/index.html.haml index 1fac06f507..f9f832d83d 100644 --- a/app/views/admin/order_cycles/index.html.haml +++ b/app/views/admin/order_cycles/index.html.haml @@ -5,8 +5,6 @@ %li#new_order_cycle_link = button_link_to "New Order Cycle", main_app.new_admin_order_cycle_path, :icon => 'icon-plus', :id => 'admin_new_order_cycle_link' - - = form_for @order_cycle_set, :url => main_app.bulk_update_admin_order_cycles_path do |f| %table.index#listing_order_cycles %colgroup From 87cc1d6217ae2f033e839c9631d79547f5811f1c Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 18 Oct 2014 01:42:58 +1100 Subject: [PATCH 19/42] create db/backup folder if it dosnt exist --- script/backup.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/script/backup.sh b/script/backup.sh index 462aef6abe..114a8352c6 100755 --- a/script/backup.sh +++ b/script/backup.sh @@ -4,4 +4,5 @@ set -e +mkdir -p db/backup ssh $1 "pg_dump -h localhost -U openfoodweb openfoodweb_production |gzip" > db/backup/$1-`date +%Y%m%d`.sql.gz From b71a40ae6dc75b7fc34389a86688cb2359ea847f Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 18 Oct 2014 03:26:57 +1100 Subject: [PATCH 20/42] show all permitted enterprises in order cycle summery --- app/views/admin/order_cycles/_row.html.haml | 4 ++-- spec/features/admin/order_cycles_spec.rb | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/views/admin/order_cycles/_row.html.haml b/app/views/admin/order_cycles/_row.html.haml index 75e84de025..3b8c6f34bc 100644 --- a/app/views/admin/order_cycles/_row.html.haml +++ b/app/views/admin/order_cycles/_row.html.haml @@ -5,12 +5,12 @@ %td= order_cycle_form.text_field :orders_open_at, :class => 'datetimepicker', :value => order_cycle.orders_open_at %td= order_cycle_form.text_field :orders_close_at, :class => 'datetimepicker', :value => order_cycle.orders_close_at %td.suppliers - - order_cycle.suppliers.managed_by(spree_current_user).each do |s| + - order_cycle.suppliers.merge(OpenFoodNetwork::Permissions.new(spree_current_user).order_cycle_enterprises).each do |s| = s.name %br/ %td= order_cycle.coordinator.name %td.distributors - - order_cycle.distributors.managed_by(spree_current_user).each do |d| + - order_cycle.distributors.merge(OpenFoodNetwork::Permissions.new(spree_current_user).order_cycle_enterprises).each do |d| = d.name %br/ diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index febd966109..be91d442e1 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -471,6 +471,10 @@ feature %q{ # I should see only the order cycle I am coordinating page.should have_content oc_user_coordinating.name page.should_not have_content oc_for_other_user.name + + # The order cycle should show enterprises that I manage + page.should have_selector 'td.suppliers', text: supplier_managed.name + page.should have_selector 'td.distributors', text: distributor_managed.name # The order cycle should not show enterprises that I don't manage page.should_not have_selector 'td.suppliers', text: supplier_unmanaged.name From 2a7dd8b8f1eeeb331d929e2a64041c6fbd1ed04d Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 18 Oct 2014 06:53:38 +1100 Subject: [PATCH 21/42] update ability specs for reports --- spec/models/spree/ability_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index 62e1973e7f..796aed2592 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -152,11 +152,11 @@ module Spree end it "should be able to read some reports" do - should have_ability([:admin, :index, :customers, :orders_and_fulfillment, :products_and_inventory], for: :reports) + should have_ability([:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory], for: :reports) end it "should not be able to read other reports" do - should_not have_ability([:sales_total, :group_buys, :bulk_coop, :payments], for: :reports) + should_not have_ability([:sales_total, :group_buys, :payments, :orders_and_distributors], for: :reports) end end @@ -247,7 +247,7 @@ module Spree end it "should be able to read some reports" do - should have_ability([:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_fulfillment, :products_and_inventory], for: :reports) + should have_ability([:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory], for: :reports) end it "should not be able to read other reports" do From 9e0f8100d935ee416c1c320034a47b6b2954a612 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Sat, 18 Oct 2014 08:28:08 +1100 Subject: [PATCH 22/42] only producers have product permissions --- app/models/spree/ability_decorator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index 4a77a2651b..1fb824d09c 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -23,7 +23,7 @@ class AbilityDecorator # Users can manage products if they have an enterprise. def can_manage_products?(user) - can_manage_enterprises? user + can_manage_enterprises?(user) && user.enterprises.is_primary_producer.present? end # Users can manage orders if they have a sells own/any enterprise. From 175e430a2bedd47ea9b8f550eeb88c55f1937364 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Wed, 22 Oct 2014 14:51:17 +1100 Subject: [PATCH 23/42] uss oop for nav check --- .../directives/navigation_check.js.coffee | 2 +- .../utils/services/navigation_check.js.coffee | 67 +++++++++++-------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee index 6f5128d7bf..95f52505eb 100644 --- a/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee +++ b/app/assets/javascripts/admin/utils/directives/navigation_check.js.coffee @@ -3,7 +3,7 @@ angular.module("admin.utils").directive "navCheck", (NavigationCheck)-> scope: navCallback: '&' link: (scope,element,attributes) -> - # Define navigationCallback on a controller in $scope, otherwise this default will be used: + # Define navigationCallback on a controller in scope, otherwise this default will be used: scope.navCallback ||= -> "You will lose any unsaved work!" NavigationCheck.register(scope.navCallback) diff --git a/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee b/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee index 1aea4e087f..ff1041474c 100644 --- a/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee +++ b/app/assets/javascripts/admin/utils/services/navigation_check.js.coffee @@ -1,37 +1,46 @@ angular.module("admin.utils") .factory "NavigationCheck", ($window, $rootScope) -> - callbacks = [] + new class NavigationCheck + callbacks = [] + constructor: -> + if $window.addEventListener + $window.addEventListener "beforeunload", @onBeforeUnloadHandler + else + $window.onbeforeunload = @onBeforeUnloadHandler - # Action for regular browser navigation. - onBeforeUnloadHandler = ($event) -> - message = getMessage() - if message - ($event or $window.event).preventDefault() + $rootScope.$on "$locationChangeStart", @locationChangeStartHandler + + + # Action for regular browser navigation. + onBeforeUnloadHandler: ($event) => + message = @getMessage() + if message + ($event or $window.event).preventDefault() + message + + # Action for angular navigation. + locationChangeStartHandler: ($event) => + message = @getMessage() + if message and not $window.confirm(message) + $event.stopPropagation() if $event.stopPropagation + $event.preventDefault() if $event.preventDefault + $event.cancelBubble = true + $event.returnValue = false + + # Runs callback functions to retreive most recently added non-empty message. + getMessage: -> + message = null + message = callback() ? message for callback in callbacks message - # Action for angular navigation. - locationChangeStartHandler = ($event) -> - message = getMessage() - if message and not $window.confirm(message) - $event.stopPropagation() if $event.stopPropagation - $event.preventDefault() if $event.preventDefault - $event.cancelBubble = true - $event.returnValue = false + register: (callback) => + callbacks.push callback - # Runs callback functions to retreive most recently added non-empty message. - getMessage = -> - message = null - message = callback() ? message for callback in callbacks - message + clear: => + if $window.addEventListener + $window.removeEventListener "beforeunload", @onBeforeUnloadHandler + else + $window.onbeforeunload = null - register = (callback) -> - callbacks.push callback + $rootScope.$on "$locationChangeStart", null - if $window.addEventListener - $window.addEventListener "beforeunload", onBeforeUnloadHandler - else - $window.onbeforeunload = onBeforeUnloadHandler - - $rootScope.$on "$locationChangeStart", locationChangeStartHandler - - return register: register From afa6119ec1aa6e9f8a3d38e2e0620574aa02345a Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Wed, 22 Oct 2014 14:53:20 +1100 Subject: [PATCH 24/42] better coverage for enterprise abilities, hide products from non producers --- spec/models/spree/ability_spec.rb | 43 +++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index c44601bb86..caf09853f1 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -12,30 +12,63 @@ module Spree let(:enterprise_any) { create(:enterprise, sells: 'any') } let(:enterprise_own) { create(:enterprise, sells: 'own') } let(:enterprise_none) { create(:enterprise, sells: 'none') } + let(:enterprise_any_producer) { create(:enterprise, sells: 'any', is_primary_producer: true) } + let(:enterprise_own_producer) { create(:enterprise, sells: 'own', is_primary_producer: true) } + let(:enterprise_none_producer) { create(:enterprise, sells: 'none', is_primary_producer: true) } - context "as manager of a 'any' type enterprise" do + context "as manager of an enterprise who sells 'any'" do before do user.enterprise_roles.create! enterprise: enterprise_any end - it { subject.can_manage_products?(user).should be_true } + it { subject.can_manage_products?(user).should be_false } it { subject.can_manage_enterprises?(user).should be_true } it { subject.can_manage_orders?(user).should be_true } end - context "as manager of a 'own' type enterprise" do + context "as manager of an enterprise who sell 'own'" do before do user.enterprise_roles.create! enterprise: enterprise_own end + it { subject.can_manage_products?(user).should be_false } + it { subject.can_manage_enterprises?(user).should be_true } + it { subject.can_manage_orders?(user).should be_true } + end + + context "as manager of an enterprise who sells 'none'" do + before do + user.enterprise_roles.create! enterprise: enterprise_none + end + + it { subject.can_manage_products?(user).should be_false } + it { subject.can_manage_enterprises?(user).should be_true } + it { subject.can_manage_orders?(user).should be_false } + end + + context "as manager of a producer enterprise who sells 'any'" do + before do + user.enterprise_roles.create! enterprise: enterprise_any_producer + end + it { subject.can_manage_products?(user).should be_true } it { subject.can_manage_enterprises?(user).should be_true } it { subject.can_manage_orders?(user).should be_true } end - context "as manager of a 'none' type enterprise" do + context "as manager of a producer enterprise who sell 'own'" do before do - user.enterprise_roles.create! enterprise: enterprise_none + user.enterprise_roles.create! enterprise: enterprise_own_producer + end + + it { subject.can_manage_products?(user).should be_true } + it { subject.can_manage_enterprises?(user).should be_true } + it { subject.can_manage_orders?(user).should be_true } + end + + context "as manager of a producer enterprise who sells 'none'" do + before do + user.enterprise_roles.create! enterprise: enterprise_none_producer end it { subject.can_manage_products?(user).should be_true } From a53cbb677d0b1537f4d9582e4ccd80cddd30918e Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Wed, 22 Oct 2014 14:55:01 +1100 Subject: [PATCH 25/42] fix report typos --- spec/models/spree/ability_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/models/spree/ability_spec.rb b/spec/models/spree/ability_spec.rb index caf09853f1..e523cce755 100644 --- a/spec/models/spree/ability_spec.rb +++ b/spec/models/spree/ability_spec.rb @@ -185,11 +185,11 @@ module Spree end it "should be able to read some reports" do - should have_ability([:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory], for: :reports) + should have_ability([:admin, :index, :customers, :bulk_coop, :orders_and_fulfillment, :products_and_inventory], for: :report) end it "should not be able to read other reports" do - should_not have_ability([:sales_total, :group_buys, :payments, :orders_and_distributors], for: :reports) + should_not have_ability([:sales_total, :group_buys, :payments, :orders_and_distributors], for: :report) end end @@ -280,16 +280,16 @@ module Spree end it "should be able to read some reports" do - should have_ability([:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory], for: :reports) + should have_ability([:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory], for: :report) end it "should not be able to read other reports" do - should_not have_ability([:sales_total], for: :reports) + should_not have_ability([:sales_total], for: :report) end end - context 'Order Cycle co-ordinator, distriutor enterprise manager' do + context 'Order Cycle co-ordinator, distributor enterprise manager' do let (:user) do user = create(:user) user.spree_roles = [] From 96ff387d1fa571b924e4cf7307e455e254f5bfe0 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Wed, 22 Oct 2014 15:34:09 +1100 Subject: [PATCH 26/42] fix navigation check on submission --- .../controllers/enterprise_controller.js.coffee | 8 ++++++-- app/views/admin/enterprises/edit.html.haml | 2 +- app/views/admin/enterprises/new.html.haml | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee index 0fa452a8d6..cfcf6319af 100644 --- a/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee +++ b/app/assets/javascripts/admin/enterprises/controllers/enterprise_controller.js.coffee @@ -1,11 +1,15 @@ angular.module("admin.enterprises") - .controller "enterpriseCtrl", ($scope, longDescription, Enterprise, PaymentMethods, ShippingMethods) -> + .controller "enterpriseCtrl", ($scope, longDescription, NavigationCheck, Enterprise, PaymentMethods, ShippingMethods) -> $scope.Enterprise = Enterprise.enterprise $scope.PaymentMethods = PaymentMethods.paymentMethods $scope.ShippingMethods = ShippingMethods.shippingMethods + $scope.navClear = NavigationCheck.clear # htmlVariable is used by textAngular wysiwyg for the long descrtiption. $scope.htmlVariable = longDescription - # Provide a callback for a warning message displayed when leaving the page. + + # Provide a callback for generating warning messages displayed before leaving the page. This is passed in + # from a directive "nav-check" in the page - if we pass it here it will be called in the test suite, + # and on all new uses of this contoller, and we might not want that . $scope.enterpriseNavCallback = -> "You are editing an enterprise!" diff --git a/app/views/admin/enterprises/edit.html.haml b/app/views/admin/enterprises/edit.html.haml index 6a8d48b24b..3c132bf5e2 100644 --- a/app/views/admin/enterprises/edit.html.haml +++ b/app/views/admin/enterprises/edit.html.haml @@ -4,7 +4,7 @@ Editing: = @enterprise.name -= form_for [main_app, :admin, @enterprise] do |f| += form_for [main_app, :admin, @enterprise], html: { "ng-app" => 'admin.enterprises', "ng-submit" => "navClear()", "ng-controller" => 'enterpriseCtrl' , "nav-check" => '', "nav-callback" => 'enterpriseNavCallback()' } do |f| = render 'ng_form', f: f .twelve.columns.alpha = render partial: 'spree/admin/shared/edit_resource_links' diff --git a/app/views/admin/enterprises/new.html.haml b/app/views/admin/enterprises/new.html.haml index 32f6ea0a8d..3df3551f47 100644 --- a/app/views/admin/enterprises/new.html.haml +++ b/app/views/admin/enterprises/new.html.haml @@ -3,7 +3,7 @@ - content_for :page_title do New Enterprise -= form_for [main_app, :admin, @enterprise] do |f| - = render partial: 'ng_form', :locals => { f: f } += form_for [main_app, :admin, @enterprise], html: { "ng-app" => 'admin.enterprises', "ng-submit" => "navClear()", "ng-controller" => 'enterpriseCtrl' , "nav-check" => '', "nav-callback" => 'enterpriseNavCallback()' } do |f| + = render 'ng_form', f: f .twelve.columns.alpha = render partial: 'spree/admin/shared/new_resource_links' From 8fb95769bf2550581a122de7d682814b293cd514 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 22 Oct 2014 17:07:45 +1100 Subject: [PATCH 27/42] Fix tested values in spec --- spec/features/admin/order_cycles_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index c579b75f7c..55623bfc18 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -627,8 +627,8 @@ feature %q{ # Then my order cycle should have been created page.should have_content 'Your order cycle has been created.' page.should have_selector 'a', text: 'Plums & Avos' - page.should have_selector "input[value='2012-11-06 06:00:00 +1100']" - page.should have_selector "input[value='2012-11-13 17:00:00 +1100']" + page.should have_selector "input[value='2014-10-17 06:00:00 +1100']" + page.should have_selector "input[value='2014-10-24 17:00:00 +1100']" # And it should have some variants selected oc = OrderCycle.last From 549ef4b79d33b9468fa27188a042c662fd73b2ee Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 22 Oct 2014 17:08:16 +1100 Subject: [PATCH 28/42] When saving an OC from the simple interface, include outgoing variants --- .../admin/order_cycles/controllers/simple.js.coffee | 3 +++ .../admin/order_cycles/services/order_cycle.js.coffee | 11 ++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee index cdc8947f25..03f4128923 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee @@ -25,3 +25,6 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl $scope.enterpriseFeesForEnterprise = (enterprise_id) -> EnterpriseFee.forEnterprise(parseInt(enterprise_id)) + $scope.submit = -> + OrderCycle.mirrorIncomingToOutgoingProducts() + OrderCycle.create() diff --git a/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee b/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee index 5e46fdda50..b53c91257e 100644 --- a/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee @@ -164,5 +164,14 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window) exchange.enterprise_fee_ids = (fee.id for fee in exchange.enterprise_fees) delete exchange.enterprise_fees order_cycle - }) + # In the simple UI, we don't list outgoing products. Instead, all products are considered + # part of both incoming and outgoing enterprises. This method mirrors the former to the + # latter **for order cycles with a single incoming and outgoing exchange only**. + mirrorIncomingToOutgoingProducts: -> + incoming = this.order_cycle.incoming_exchanges[0] + outgoing = this.order_cycle.outgoing_exchanges[0] + + for id, active of incoming.variants + outgoing.variants[id] = active + }) From 28352be72946015f3c91a8354db528a1eca440ca Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 22 Oct 2014 17:17:05 +1100 Subject: [PATCH 29/42] Save pickup time and instructions --- .../javascripts/admin/order_cycles/controllers/simple.js.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee index 03f4128923..83f0999b30 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee @@ -3,6 +3,7 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl enterprise = enterprises[Object.keys(enterprises)[0]] OrderCycle.addSupplier enterprise.id OrderCycle.addDistributor enterprise.id + $scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0] OrderCycle.setExchangeVariants(OrderCycle.order_cycle.incoming_exchanges[0], Enterprise.suppliedVariants(enterprise.id), true) From 69614d6cf149782c47a88e3e02a92210081fbef9 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Wed, 22 Oct 2014 17:23:06 +1100 Subject: [PATCH 30/42] fix accordion jumps --- app/views/checkout/_shipping.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/checkout/_shipping.html.haml b/app/views/checkout/_shipping.html.haml index 27089527a2..5ba5ed15e4 100644 --- a/app/views/checkout/_shipping.html.haml +++ b/app/views/checkout/_shipping.html.haml @@ -83,4 +83,4 @@ .row .small-12.columns.text-right - %button.primary{"ng-disabled" => "shipping.$invalid", "ng-click" => "next($event)", "ofn-focus" => "accordion['shipping']"} Next + %button.primary{"ng-disabled" => "shipping.$invalid", "ng-click" => "next($event)"} Next From 3e61aa72677213f5a063f761d5cc38c9212cc7f5 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 22 Oct 2014 17:26:22 +1100 Subject: [PATCH 31/42] Simple interface remove coordinator fee --- .../admin/order_cycles/controllers/simple.js.coffee | 4 ++++ spec/features/admin/order_cycles_spec.rb | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee index 83f0999b30..4499cd833b 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee @@ -23,6 +23,10 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl $event.preventDefault() OrderCycle.addCoordinatorFee() + $scope.removeCoordinatorFee = ($event, index) -> + $event.preventDefault() + OrderCycle.removeCoordinatorFee(index) + $scope.enterpriseFeesForEnterprise = (enterprise_id) -> EnterpriseFee.forEnterprise(parseInt(enterprise_id)) diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 55623bfc18..153f34f4a7 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -621,6 +621,11 @@ feature %q{ # And I add a fee and save click_button 'Add coordinator fee' + click_button 'Add coordinator fee' + click_link 'order_cycle_coordinator_fee_1_remove' + page.should have_select 'order_cycle_coordinator_fee_0_id' + page.should_not have_select 'order_cycle_coordinator_fee_1_id' + select 'Coord fee', from: 'order_cycle_coordinator_fee_0_id' click_button 'Create' From 069b9ce91d89cf489488ca0950b8b69b7df4d656 Mon Sep 17 00:00:00 2001 From: Rafael Schouten Date: Wed, 22 Oct 2014 17:49:31 +1100 Subject: [PATCH 32/42] fix email length validation spec --- spec/models/enterprise_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index 7adeb08d2d..206be1e131 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -105,7 +105,7 @@ describe Enterprise do subject { FactoryGirl.create(:distributor_enterprise, :address => FactoryGirl.create(:address)) } it { should validate_presence_of(:name) } it { should validate_presence_of(:email) } - it { should validate_length_of(:description, :maximum => 255) } + it { should ensure_length_of(:description).is_at_most(255) } it "requires an owner" do expect{ From d47db903fb6535010ef6fb54b3cbad5b0b6a47d9 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 22 Oct 2014 19:12:51 +1100 Subject: [PATCH 33/42] Add basic styling to simple order cycle interface --- .../_name_and_timing_form.html.haml | 24 +++++++++++-------- .../admin/order_cycles/_simple_form.html.haml | 18 ++++++++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/app/views/admin/order_cycles/_name_and_timing_form.html.haml b/app/views/admin/order_cycles/_name_and_timing_form.html.haml index 437a6a44f7..ed24d20f39 100644 --- a/app/views/admin/order_cycles/_name_and_timing_form.html.haml +++ b/app/views/admin/order_cycles/_name_and_timing_form.html.haml @@ -1,11 +1,15 @@ -= f.label :name -= f.text_field :name, 'ng-model' => 'order_cycle.name', 'required' => true -%br/ +.row + .alpha.two.columns + = f.label :name + .fourteen.columns.omega + = f.text_field :name, 'ng-model' => 'order_cycle.name', 'required' => true -.date-field - = f.label :orders_open_at, 'Orders open' - = f.text_field :orders_open_at, 'datetimepicker' => 'order_cycle.orders_open_at', 'ng-model' => 'order_cycle.orders_open_at' -.date-field - = f.label :orders_close_at, 'Orders close' - = f.text_field :orders_close_at, 'datetimepicker' => 'order_cycle.orders_close_at', 'ng-model' => 'order_cycle.orders_close_at' -%br/ +.row + .alpha.two.columns + = f.label :orders_open_at, 'Orders open' + .six.columns + = f.text_field :orders_open_at, 'datetimepicker' => 'order_cycle.orders_open_at', 'ng-model' => 'order_cycle.orders_open_at' + .two.columns + = f.label :orders_close_at, 'Orders close' + .six.columns.omega + = f.text_field :orders_close_at, 'datetimepicker' => 'order_cycle.orders_close_at', 'ng-model' => 'order_cycle.orders_close_at' diff --git a/app/views/admin/order_cycles/_simple_form.html.haml b/app/views/admin/order_cycles/_simple_form.html.haml index 37f7ab0152..912631bb37 100644 --- a/app/views/admin/order_cycles/_simple_form.html.haml +++ b/app/views/admin/order_cycles/_simple_form.html.haml @@ -1,11 +1,19 @@ = render 'name_and_timing_form', f: f -= text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => 'Ready for (ie. Date / Time)', 'ng-model' => 'outgoing_exchange.pickup_time' -%br/ -= text_field_tag 'order_cycle_outgoing_exchange_0_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_instructions', 'placeholder' => 'Pick-up instructions', 'ng-model' => 'outgoing_exchange.pickup_instructions' +.row + .alpha.two.columns + = label_tag 'Pickup time' + .six.columns + = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => 'Ready for (ie. Date / Time)', 'ng-model' => 'outgoing_exchange.pickup_time' + .two.columns + = label_tag 'Pickup instructions' + .six.columns.omega + = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_instructions', 'placeholder' => 'Pick-up instructions', 'ng-model' => 'outgoing_exchange.pickup_instructions' -%div{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}} - = render 'exchange_supplied_products_form' +%table.exchanges + %tbody{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}} + %tr.products + = render 'exchange_supplied_products_form' = render 'coordinator_fees', f: f From 66e13d40f4267b49828f0f8573be9ba6c2d10ebb Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 22 Oct 2014 19:17:28 +1100 Subject: [PATCH 34/42] Select all works on simple order cycles interface --- .../admin/order_cycles/controllers/simple.js.coffee | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee index 4499cd833b..728b27fb4a 100644 --- a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee @@ -19,6 +19,12 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl $scope.removeDistributionOfVariant = angular.noop + $scope.setExchangeVariants = (exchange, variants, selected) -> + OrderCycle.setExchangeVariants(exchange, variants, selected) + + $scope.suppliedVariants = (enterprise_id) -> + Enterprise.suppliedVariants(enterprise_id) + $scope.addCoordinatorFee = ($event) -> $event.preventDefault() OrderCycle.addCoordinatorFee() From f74ec03cefe3b9002aa4d68b9da5d25d9d2f030f Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 09:26:55 +1100 Subject: [PATCH 35/42] Rename --- .../controllers/{simple.js.coffee => simple_edit.js.coffee} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/assets/javascripts/admin/order_cycles/controllers/{simple.js.coffee => simple_edit.js.coffee} (100%) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee similarity index 100% rename from app/assets/javascripts/admin/order_cycles/controllers/simple.js.coffee rename to app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee From 2ad823a79d3da5e6140831a4019182b479bf0927 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 09:39:23 +1100 Subject: [PATCH 36/42] Fix JS specs --- spec/javascripts/unit/order_cycle_spec.js.coffee | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/javascripts/unit/order_cycle_spec.js.coffee b/spec/javascripts/unit/order_cycle_spec.js.coffee index 2a8d001804..7ecd2b4782 100644 --- a/spec/javascripts/unit/order_cycle_spec.js.coffee +++ b/spec/javascripts/unit/order_cycle_spec.js.coffee @@ -38,7 +38,7 @@ describe 'OrderCycle controllers', -> index: jasmine.createSpy('index').andReturn('enterprise fees list') forEnterprise: jasmine.createSpy('forEnterprise').andReturn('enterprise fees for enterprise') - module('order_cycle') + module('admin.order_cycles') inject ($controller) -> ctrl = $controller 'AdminCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee} @@ -198,7 +198,7 @@ describe 'OrderCycle controllers', -> index: jasmine.createSpy('index').andReturn('enterprise fees list') forEnterprise: jasmine.createSpy('forEnterprise').andReturn('enterprise fees for enterprise') - module('order_cycle') + module('admin.order_cycles') inject ($controller) -> ctrl = $controller 'AdminEditOrderCycleCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee} @@ -323,7 +323,7 @@ describe 'OrderCycle services', -> Enterprise = null beforeEach -> - module 'order_cycle' + module 'admin.order_cycles' inject ($injector, _$httpBackend_)-> Enterprise = $injector.get('Enterprise') $httpBackend = _$httpBackend_ @@ -389,7 +389,7 @@ describe 'OrderCycle services', -> EnterpriseFee = null beforeEach -> - module 'order_cycle' + module 'admin.order_cycles' inject ($injector, _$httpBackend_)-> EnterpriseFee = $injector.get('EnterpriseFee') $httpBackend = _$httpBackend_ @@ -431,7 +431,7 @@ describe 'OrderCycle services', -> beforeEach -> $window = {navigator: {userAgent: 'foo'}} - module 'order_cycle', ($provide)-> + module 'admin.order_cycles', ($provide)-> $provide.value('$window', $window) null From 8b616e7d17ebf389ea2d706620758b978542a869 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 10:21:19 +1100 Subject: [PATCH 37/42] Add unit spec for order cycles simple create controller --- .../controllers/simple_edit.js.coffee | 10 ++-- .../controllers/simple_edit.js.coffee | 49 +++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee 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 728b27fb4a..e2a60e424e 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 @@ -1,19 +1,21 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, OrderCycle, Enterprise, EnterpriseFee) -> $scope.enterprises = Enterprise.index (enterprises) => + $scope.init(enterprises) + $scope.enterprise_fees = EnterpriseFee.index() + $scope.order_cycle = OrderCycle.order_cycle + + $scope.init = (enterprises) -> enterprise = enterprises[Object.keys(enterprises)[0]] OrderCycle.addSupplier enterprise.id OrderCycle.addDistributor enterprise.id $scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0] + # All variants start as checked OrderCycle.setExchangeVariants(OrderCycle.order_cycle.incoming_exchanges[0], Enterprise.suppliedVariants(enterprise.id), true) OrderCycle.order_cycle.coordinator_id = enterprise.id - $scope.enterprise_fees = EnterpriseFee.index() - - $scope.order_cycle = OrderCycle.order_cycle - $scope.loaded = -> Enterprise.loaded && EnterpriseFee.loaded diff --git a/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee b/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee new file mode 100644 index 0000000000..bf2498e234 --- /dev/null +++ b/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee @@ -0,0 +1,49 @@ +describe "AdminSimpleCreateOrderCycleCtrl", -> + ctrl = null + scope = {} + OrderCycle = {} + Enterprise = {} + EnterpriseFee = {} + incoming_exchange = {} + outgoing_exchange = {} + + beforeEach -> + scope = {} + OrderCycle = + order_cycle: + incoming_exchanges: [incoming_exchange] + outgoing_exchanges: [outgoing_exchange] + addSupplier: jasmine.createSpy() + addDistributor: jasmine.createSpy() + setExchangeVariants: jasmine.createSpy() + Enterprise = + index: jasmine.createSpy() + suppliedVariants: jasmine.createSpy().andReturn('supplied variants') + EnterpriseFee = + index: jasmine.createSpy() + + module('admin.order_cycles') + inject ($controller) -> + ctrl = $controller 'AdminSimpleCreateOrderCycleCtrl', {$scope: scope, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee} + + describe "initialisation", -> + enterprise = {id: 123} + enterprises = {123: enterprise} + + beforeEach -> + scope.init(enterprises) + + it "sets up an incoming and outgoing exchange", -> + expect(OrderCycle.addSupplier).toHaveBeenCalledWith(enterprise.id) + expect(OrderCycle.addDistributor).toHaveBeenCalledWith(enterprise.id) + expect(scope.outgoing_exchange).toEqual outgoing_exchange + + it "selects all variants", -> + expect(Enterprise.suppliedVariants). + toHaveBeenCalledWith(enterprise.id) + + expect(OrderCycle.setExchangeVariants). + toHaveBeenCalledWith(incoming_exchange, 'supplied variants', true) + + it "sets the coordinator", -> + expect(OrderCycle.order_cycle.coordinator_id).toEqual enterprise.id \ No newline at end of file From 56ebe688dc74b4454b3ad441feaf200b996284da Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 10:22:03 +1100 Subject: [PATCH 38/42] Fix file naming --- .../{simple_edit.js.coffee => simple_create.js.coffee} | 0 .../{simple_edit.js.coffee => simple_create.js.coffee} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename app/assets/javascripts/admin/order_cycles/controllers/{simple_edit.js.coffee => simple_create.js.coffee} (100%) rename spec/javascripts/unit/admin/order_cycles/controllers/{simple_edit.js.coffee => simple_create.js.coffee} (100%) diff --git a/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee b/app/assets/javascripts/admin/order_cycles/controllers/simple_create.js.coffee similarity index 100% rename from app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee rename to app/assets/javascripts/admin/order_cycles/controllers/simple_create.js.coffee diff --git a/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee b/spec/javascripts/unit/admin/order_cycles/controllers/simple_create.js.coffee similarity index 100% rename from spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee rename to spec/javascripts/unit/admin/order_cycles/controllers/simple_create.js.coffee From f7c1340f9945585c49dbf986b1589cc5c5e7e2c6 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 11:08:27 +1100 Subject: [PATCH 39/42] Admin can view an order cycle in the simple edit form --- .../controllers/simple_edit.js.coffee | 14 +++++++ .../services/order_cycle.js.coffee | 4 +- app/views/admin/order_cycles/edit.html.haml | 9 ++++- spec/features/admin/order_cycles_spec.rb | 31 +++++++++++++++ .../controllers/simple_edit.js.coffee | 38 +++++++++++++++++++ 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee create mode 100644 spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee 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 new file mode 100644 index 0000000000..bceef1b0ef --- /dev/null +++ b/app/assets/javascripts/admin/order_cycles/controllers/simple_edit.js.coffee @@ -0,0 +1,14 @@ +angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, OrderCycle, Enterprise, EnterpriseFee) -> + $scope.enterprises = Enterprise.index() + $scope.enterprise_fees = EnterpriseFee.index() + $scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) => + $scope.init() + + $scope.orderCycleId = -> + $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1] + + $scope.init = -> + $scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0] + + $scope.enterpriseFeesForEnterprise = (enterprise_id) -> + EnterpriseFee.forEnterprise(parseInt(enterprise_id)) diff --git a/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee b/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee index b53c91257e..687a0164fa 100644 --- a/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee +++ b/app/assets/javascripts/admin/order_cycles/services/order_cycle.js.coffee @@ -84,7 +84,7 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window) for exchange in this.order_cycle.outgoing_exchanges exchange.variants[variant_id] = false - load: (order_cycle_id) -> + load: (order_cycle_id, callback=null) -> service = this OrderCycle.get {order_cycle_id: order_cycle_id}, (oc) -> angular.extend(service.order_cycle, oc) @@ -104,6 +104,8 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window) delete(service.order_cycle.exchanges) service.loaded = true + (callback || angular.noop)(service.order_cycle) + this.order_cycle create: -> diff --git a/app/views/admin/order_cycles/edit.html.haml b/app/views/admin/order_cycles/edit.html.haml index b22f0cf51d..ff40cfbbbc 100644 --- a/app/views/admin/order_cycles/edit.html.haml +++ b/app/views/admin/order_cycles/edit.html.haml @@ -1,4 +1,9 @@ %h1 Edit Order Cycle -= form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.order_cycles', 'ng-controller' => 'AdminEditOrderCycleCtrl', 'ng-submit' => 'submit()'} do |f| - = render 'form', :f => f +- ng_controller = order_cycles_simple_view ? 'AdminSimpleEditOrderCycleCtrl' : 'AdminEditOrderCycleCtrl' + += form_for [main_app, :admin, @order_cycle], :url => '', :html => {:class => 'ng order_cycle', 'ng-app' => 'admin.order_cycles', 'ng-controller' => ng_controller, 'ng-submit' => 'submit()'} do |f| + - if order_cycles_simple_view + = render 'simple_form', f: f + - else + = render 'form', f: f diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 153f34f4a7..3cff362f56 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -648,6 +648,37 @@ feature %q{ ex.pickup_time.should == 'pickup time' ex.pickup_instructions.should == 'pickup instructions' end + + scenario "editing an order cycle" do + # Given an order cycle + fee = create(:enterprise_fee, name: 'my fee', enterprise: enterprise) + oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee]) + + # And the order cycle has a pickup time and pickup instructions + ex = oc.exchanges.outgoing.first + ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions' + + # When I edit it + login_to_admin_section + click_link 'Order Cycles' + click_link oc.name + wait_until { page.find('#order_cycle_name').value.present? } + + # Then I should see the basic settings + page.should have_field 'order_cycle_name', with: oc.name + page.should have_field 'order_cycle_orders_open_at', with: oc.orders_open_at.to_s + page.should have_field 'order_cycle_orders_close_at', with: oc.orders_close_at.to_s + page.should have_field 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time' + page.should have_field 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions' + + # And I should see the products + page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p1.master.id}" + page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{p2.master.id}" + page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{v.id}" + + # And I should see the coordinator fees + page.should have_select 'order_cycle_coordinator_fee_0_id', selected: 'my fee' + end end diff --git a/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee b/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee new file mode 100644 index 0000000000..0e3275d886 --- /dev/null +++ b/spec/javascripts/unit/admin/order_cycles/controllers/simple_edit.js.coffee @@ -0,0 +1,38 @@ +describe "AdminSimpleEditOrderCycleCtrl", -> + ctrl = null + scope = {} + location = {} + OrderCycle = {} + Enterprise = {} + EnterpriseFee = {} + incoming_exchange = {} + outgoing_exchange = {} + + beforeEach -> + scope = {} + location = + absUrl: -> + 'example.com/admin/order_cycles/27/edit' + OrderCycle = + order_cycle: + incoming_exchanges: [incoming_exchange] + outgoing_exchanges: [outgoing_exchange] + load: jasmine.createSpy() + Enterprise = + index: jasmine.createSpy() + EnterpriseFee = + index: jasmine.createSpy() + + module('admin.order_cycles') + inject ($controller) -> + ctrl = $controller 'AdminSimpleEditOrderCycleCtrl', {$scope: scope, $location: location, OrderCycle: OrderCycle, Enterprise: Enterprise, EnterpriseFee: EnterpriseFee} + + describe "initialisation", -> + enterprise = {id: 123} + enterprises = {123: enterprise} + + beforeEach -> + scope.init(enterprises) + + it "sets the outgoing exchange", -> + expect(scope.outgoing_exchange).toEqual outgoing_exchange From ab76c66b6837005ee0858772bc76fb5e2955b3a6 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 11:38:15 +1100 Subject: [PATCH 40/42] Admin can update order cycles with simple interface --- .../controllers/simple_edit.js.coffee | 21 ++++++- spec/features/admin/order_cycles_spec.rb | 58 ++++++++++++++++++- 2 files changed, 74 insertions(+), 5 deletions(-) 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 bceef1b0ef..512bc0460b 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 @@ -1,14 +1,31 @@ angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, OrderCycle, Enterprise, EnterpriseFee) -> + $scope.orderCycleId = -> + $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1] + $scope.enterprises = Enterprise.index() $scope.enterprise_fees = EnterpriseFee.index() $scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) => $scope.init() - $scope.orderCycleId = -> - $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1] + $scope.loaded = -> + Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded $scope.init = -> $scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0] $scope.enterpriseFeesForEnterprise = (enterprise_id) -> EnterpriseFee.forEnterprise(parseInt(enterprise_id)) + + $scope.removeDistributionOfVariant = angular.noop + + $scope.addCoordinatorFee = ($event) -> + $event.preventDefault() + OrderCycle.addCoordinatorFee() + + $scope.removeCoordinatorFee = ($event, index) -> + $event.preventDefault() + OrderCycle.removeCoordinatorFee(index) + + $scope.submit = -> + OrderCycle.mirrorIncomingToOutgoingProducts() + OrderCycle.update() diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb index 3cff362f56..56f3b62916 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles_spec.rb @@ -650,11 +650,9 @@ feature %q{ end scenario "editing an order cycle" do - # Given an order cycle + # Given an order cycle with pickup time and instructions fee = create(:enterprise_fee, name: 'my fee', enterprise: enterprise) oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee]) - - # And the order cycle has a pickup time and pickup instructions ex = oc.exchanges.outgoing.first ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions' @@ -679,6 +677,60 @@ feature %q{ # And I should see the coordinator fees page.should have_select 'order_cycle_coordinator_fee_0_id', selected: 'my fee' end + + scenario "updating an order cycle" do + # Given an order cycle with pickup time and instructions + fee1 = create(:enterprise_fee, name: 'my fee', enterprise: enterprise) + fee2 = create(:enterprise_fee, name: 'that fee', enterprise: enterprise) + oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee1]) + ex = oc.exchanges.outgoing.first + ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions' + + # When I edit it + login_to_admin_section + visit edit_admin_order_cycle_path oc + wait_until { page.find('#order_cycle_name').value.present? } + + # And I fill in the basic fields + fill_in 'order_cycle_name', with: 'Plums & Avos' + fill_in 'order_cycle_orders_open_at', with: '2014-10-17 06:00:00' + fill_in 'order_cycle_orders_close_at', with: '2014-10-24 17:00:00' + fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'xy' + fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'zzy' + + # And I make some product selections + uncheck "order_cycle_incoming_exchange_0_variants_#{p1.master.id}" + check "order_cycle_incoming_exchange_0_variants_#{p2.master.id}" + check "order_cycle_incoming_exchange_0_variants_#{v.id}" + uncheck "order_cycle_incoming_exchange_0_variants_#{v.id}" + + # And I select some fees and update + click_link 'order_cycle_coordinator_fee_0_remove' + page.should_not have_select 'order_cycle_coordinator_fee_0_id' + click_button 'Add coordinator fee' + select 'that fee', from: 'order_cycle_coordinator_fee_0_id' + + click_button 'Update' + + # Then my order cycle should have been updated + page.should have_content 'Your order cycle has been updated.' + page.should have_selector 'a', text: 'Plums & Avos' + page.should have_selector "input[value='2014-10-17 06:00:00 +1100']" + page.should have_selector "input[value='2014-10-24 17:00:00 +1100']" + + # And it should have a variant selected + oc = OrderCycle.last + oc.exchanges.incoming.first.variants.should == [p2.master] + oc.exchanges.outgoing.first.variants.should == [p2.master] + + # And it should have the fee + oc.coordinator_fees.should == [fee2] + + # And my pickup time and instructions should have been saved + ex = oc.exchanges.outgoing.first + ex.pickup_time.should == 'xy' + ex.pickup_instructions.should == 'zzy' + end end From 7faf6e12eacba9e8d10358f72d76168c55db4bf2 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 15:53:16 +1100 Subject: [PATCH 41/42] Clean up simple order cycle interface --- app/views/admin/order_cycles/_simple_form.html.haml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/views/admin/order_cycles/_simple_form.html.haml b/app/views/admin/order_cycles/_simple_form.html.haml index 912631bb37..9bffb9753e 100644 --- a/app/views/admin/order_cycles/_simple_form.html.haml +++ b/app/views/admin/order_cycles/_simple_form.html.haml @@ -2,19 +2,22 @@ .row .alpha.two.columns - = label_tag 'Pickup time' + = label_tag 'Ready for' .six.columns - = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => 'Ready for (ie. Date / Time)', 'ng-model' => 'outgoing_exchange.pickup_time' + = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_time', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_time', 'placeholder' => 'Date / time', 'ng-model' => 'outgoing_exchange.pickup_time', 'size' => 30 .two.columns - = label_tag 'Pickup instructions' + = label_tag 'Customer instructions' .six.columns.omega - = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_instructions', 'placeholder' => 'Pick-up instructions', 'ng-model' => 'outgoing_exchange.pickup_instructions' + = text_field_tag 'order_cycle_outgoing_exchange_0_pickup_instructions', '', 'id' => 'order_cycle_outgoing_exchange_0_pickup_instructions', 'placeholder' => 'Pick-up or delivery notes', 'ng-model' => 'outgoing_exchange.pickup_instructions', 'size' => 30 += label_tag 'Products' %table.exchanges %tbody{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}} %tr.products = render 'exchange_supplied_products_form' +%br/ += label_tag 'Fees' = render 'coordinator_fees', f: f .actions From f09698be47785fd0f02d6a56375b88f404f82e06 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 23 Oct 2014 15:54:52 +1100 Subject: [PATCH 42/42] Select all works on simple order cycles edit interface --- .../admin/order_cycles/controllers/simple_edit.js.coffee | 6 ++++++ 1 file changed, 6 insertions(+) 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 512bc0460b..bcdaa64e91 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 @@ -18,6 +18,12 @@ angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl", $scope.removeDistributionOfVariant = angular.noop + $scope.setExchangeVariants = (exchange, variants, selected) -> + OrderCycle.setExchangeVariants(exchange, variants, selected) + + $scope.suppliedVariants = (enterprise_id) -> + Enterprise.suppliedVariants(enterprise_id) + $scope.addCoordinatorFee = ($event) -> $event.preventDefault() OrderCycle.addCoordinatorFee()