diff --git a/app/assets/javascripts/admin/bulk_order_management.js.coffee b/app/assets/javascripts/admin/bulk_order_management.js.coffee index 36fd7a8de0..58eb0c85c0 100644 --- a/app/assets/javascripts/admin/bulk_order_management.js.coffee +++ b/app/assets/javascripts/admin/bulk_order_management.js.coffee @@ -6,7 +6,7 @@ orderManagementModule.config [ provider.defaults.headers.common["X-CSRF-Token"] = $("meta[name=csrf-token]").attr("content") ] -orderManagementModule.value "blankEnterprise", -> +orderManagementModule.value "blankOption", -> { id: "", name: "All" } orderManagementModule.directive "ofnLineItemUpdAttr", [ @@ -103,8 +103,8 @@ orderManagementModule.factory "pendingChanges",[ orderManagementModule.controller "AdminOrderMgmtCtrl", [ - "$scope", "$http", "dataFetcher", "blankEnterprise", "pendingChanges" - ($scope, $http, dataFetcher, blankEnterprise, pendingChanges) -> + "$scope", "$http", "dataFetcher", "blankOption", "pendingChanges" + ($scope, $http, dataFetcher, blankOption, pendingChanges) -> now = new Date start = new Date( now.getTime() - ( 7 * (1440 * 60 * 1000) ) - (now.getTime() - now.getTimezoneOffset() * 60 * 1000) % (1440 * 60 * 1000) ) @@ -124,13 +124,18 @@ orderManagementModule.controller "AdminOrderMgmtCtrl", [ $http.defaults.headers.common["X-Spree-Token"] = spree_api_key dataFetcher("/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true").then (data) -> $scope.suppliers = data - $scope.suppliers.unshift blankEnterprise() + $scope.suppliers.unshift blankOption() $scope.supplierFilter = $scope.suppliers[0] dataFetcher("/api/enterprises/managed?template=bulk_index&q[is_distributor_eq]=true").then (data) -> $scope.distributors = data - $scope.distributors.unshift blankEnterprise() + $scope.distributors.unshift blankOption() $scope.distributorFilter = $scope.distributors[0] - $scope.fetchOrders() + dataFetcher("/api/order_cycles/managed").then (data) -> + $scope.orderCycles = data + $scope.matchOrderCycleEnterprises orderCycle for orderCycle in $scope.orderCycles + $scope.orderCycles.unshift blankOption() + $scope.orderCycleFilter = $scope.orderCycles[0] + $scope.fetchOrders() else if authorise_api_reponse.hasOwnProperty("error") $scope.api_error_msg = authorise_api_reponse("error") else @@ -146,27 +151,30 @@ orderManagementModule.controller "AdminOrderMgmtCtrl", [ $scope.orders = data $scope.resetLineItems() pendingChanges.removeAll() - $scope.matchDistributor order for order in $scope.orders + for i,order of $scope.orders + order.distributor = $scope.matchObject $scope.distributors, order.distributor, null + order.order_cycle = $scope.matchObject $scope.orderCycles, order.order_cycle, null $scope.resetLineItems = -> $scope.lineItems = $scope.orders.reduce (lineItems,order) -> for i,line_item of order.line_items - $scope.matchSupplier line_item + line_item.supplier = $scope.matchObject $scope.suppliers, line_item.supplier, null line_item.order = order lineItems.concat order.line_items , [] - $scope.matchSupplier = (line_item) -> - for i, supplier of $scope.suppliers - if angular.equals(supplier, line_item.supplier) - line_item.supplier = supplier - break + $scope.matchOrderCycleEnterprises = (orderCycle) -> + for i,distributor of orderCycle.distributors + orderCycle.distributors[i] = $scope.matchObject $scope.distributors, distributor, null + for i,supplier of orderCycle.suppliers + orderCycle.suppliers[i] = $scope.matchObject $scope.suppliers, supplier, null - $scope.matchDistributor = (order) -> - for i, distributor of $scope.distributors - if angular.equals(distributor, order.distributor) - order.distributor = distributor - break + $scope.matchObject = (list, testObject, noMatch) -> + for i, object of list + if angular.equals(object, testObject) + return object + else + return noMatch $scope.deleteLineItem = (lineItem) -> if ($scope.confirmDelete && confirm("Are you sure?")) || !$scope.confirmDelete @@ -179,12 +187,13 @@ orderManagementModule.controller "AdminOrderMgmtCtrl", [ ] orderManagementModule.filter "selectFilter", [ - "blankEnterprise" - (blankEnterprise) -> - return (lineItems,selectedSupplier,selectedDistributor) -> + "blankOption" + (blankOption) -> + return (lineItems,selectedSupplier,selectedDistributor,selectedOrderCycle) -> filtered = [] - filtered.push line_item for line_item in lineItems when (angular.equals(selectedSupplier,blankEnterprise()) || line_item.supplier == selectedSupplier) && - (angular.equals(selectedDistributor,blankEnterprise()) || line_item.order.distributor == selectedDistributor) + filtered.push line_item for line_item in lineItems when (angular.equals(selectedSupplier,blankOption()) || line_item.supplier == selectedSupplier) && + (angular.equals(selectedDistributor,blankOption()) || line_item.order.distributor == selectedDistributor) && + (angular.equals(selectedOrderCycle,blankOption()) || line_item.order.order_cycle == selectedOrderCycle) filtered ] diff --git a/app/views/spree/admin/orders/bulk_management.html.haml b/app/views/spree/admin/orders/bulk_management.html.haml index 32e737d4b1..153ec4fe30 100644 --- a/app/views/spree/admin/orders/bulk_management.html.haml +++ b/app/views/spree/admin/orders/bulk_management.html.haml @@ -8,22 +8,26 @@ {{ api_error_msg }} .filter_selects{ :class => "four columns alpha" } .filter_select{ :class => "four columns alpha" } - Producer + %label{ :for => 'supplier_filter' }Producer %br %select.select2{ :class => "four columns alpha", :id => 'supplier_filter', 'ng-model' => 'supplierFilter', 'ng-options' => 's.name for s in suppliers' } .filter_select{ :class => "four columns alpha" } - Hub + %label{ :for => 'distributor_filter' }Hub %br %select.select2{ :class => "four columns alpha", :id => 'distributor_filter', 'ng-model' => 'distributorFilter', 'ng-options' => 'd.name for d in distributors'} + .filter_select{ :class => "four columns alpha" } + %label{ :for => 'order_cycle_filter' }Order Cycle + %br + %select.select2{ :class => "four columns alpha", :id => 'order_cycle_filter', 'ng-model' => 'orderCycleFilter', 'ng-options' => 'oc.name for oc in orderCycles'} .spacer{ :class => "one column alpha" }   .date_filters{ :class => "four columns alpha" } .date_filter{ :class => "four columns alpha" } - Start Date + %label{ :for => 'start_date_filter' }Start Date %br %input{ :class => "four columns alpha", :type => "text", :id => 'start_date_filter', 'ng-model' => 'startDate', 'datetimepicker' => "startDate", 'ofn-confirm-change' => "startDate" } .date_filter{ :class => "four columns alpha" } - End Date + %label{ :for => 'end_date_filter' }End Date %br %input{ :class => "four columns alpha", :type => "text", :id => 'end_date_filter', 'ng-model' => 'endDate', 'datetimepicker' => "endDate", 'ofn-confirm-change' => "endDate" } .spacer{ :class => "seven columns alpha" } @@ -46,7 +50,7 @@ %th.actions Ask?  %input{ :type => 'checkbox', 'ng-model' => "confirmDelete" } - %tr.line_item{ 'ng-repeat' => 'line_item in lineItems | selectFilter:supplierFilter:distributorFilter', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'", :id => "li_{{line_item.id}}" } + %tr.line_item{ 'ng-repeat' => 'line_item in lineItems | selectFilter:supplierFilter:distributorFilter:orderCycleFilter', 'ng-class-even' => "'even'", 'ng-class-odd' => "'odd'", :id => "li_{{line_item.id}}" } %td.email {{ line_item.order.email }} %td.date {{ line_item.order.completed_at }} %td.producer {{ line_item.supplier.name }} diff --git a/app/views/spree/api/orders/bulk_show.v1.rabl b/app/views/spree/api/orders/bulk_show.v1.rabl index 07394743e5..4e77763d6e 100644 --- a/app/views/spree/api/orders/bulk_show.v1.rabl +++ b/app/views/spree/api/orders/bulk_show.v1.rabl @@ -2,6 +2,7 @@ object @order attributes :id, :number, :email node( :completed_at ) { |order| order.completed_at.blank? ? "" : order.completed_at.strftime("%F %T") } node( :distributor ) { |order| partial 'spree/api/enterprises/bulk_show', :object => order.distributor } +node( :order_cycle ) { |order| partial 'api/order_cycles/bulk_show', :object => order.order_cycle } node( :line_items ) do |order| order.line_items.order('id ASC').map do |line_item| partial 'spree/api/line_items/bulk_show', :object => line_item diff --git a/spec/controllers/spree/api/orders_controller_spec.rb b/spec/controllers/spree/api/orders_controller_spec.rb index 21bf816cef..8961cc8070 100644 --- a/spec/controllers/spree/api/orders_controller_spec.rb +++ b/spec/controllers/spree/api/orders_controller_spec.rb @@ -14,7 +14,7 @@ module Spree let!(:line_item2) { FactoryGirl.create(:line_item, order: order2) } let!(:line_item3) { FactoryGirl.create(:line_item, order: order2) } let!(:line_item4) { FactoryGirl.create(:line_item, order: order3) } - let(:order_attributes) { [:id, :email, :completed_at, :line_items, :distributor, :number] } + let(:order_attributes) { [:id, :email, :completed_at, :line_items, :distributor, :order_cycle, :number] } let(:line_item_attributes) { [:id, :quantity, :max_quantity, :supplier, :variant_unit_text] } before do diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index abcf940b65..15d4f8bd78 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -159,14 +159,16 @@ feature %q{ end context "using drop down seletors" do - let!(:s1) { FactoryGirl.create(:supplier_enterprise) } - let!(:s2) { FactoryGirl.create(:supplier_enterprise) } - let!(:d1) { FactoryGirl.create(:distributor_enterprise) } - let!(:d2) { FactoryGirl.create(:distributor_enterprise) } - let!(:p1) { FactoryGirl.create(:product, supplier: s1 ) } - let!(:p2) { FactoryGirl.create(:product, supplier: s2 ) } - let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d1 ) } - let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d2 ) } + let!(:oc1) { FactoryGirl.create(:order_cycle) } + let!(:oc2) { FactoryGirl.create(:order_cycle) } + let!(:s1) { oc1.suppliers.first } + let!(:s2) { oc2.suppliers.last } + let!(:d1) { oc1.distributors.first } + let!(:d2) { oc2.distributors.last } + let!(:p1) { FactoryGirl.create(:product, supplier: s1) } + let!(:p2) { FactoryGirl.create(:product, supplier: s2) } + let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d1, order_cycle: oc1 ) } + let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, distributor: d2, order_cycle: oc2 ) } let!(:li1) { FactoryGirl.create(:line_item, order: o1, product: p1 ) } let!(:li2) { FactoryGirl.create(:line_item, order: o2, product: p2 ) } @@ -209,6 +211,24 @@ feature %q{ page.should have_selector "tr#li_#{li1.id}", visible: true page.should have_selector "tr#li_#{li2.id}", visible: true end + + it "displays a select box for order cycles, which filters line items by the selected order cycle" do + page.should have_select "order_cycle_filter", with_options: [oc1.name,oc2.name] + page.should have_selector "tr#li_#{li1.id}", visible: true + page.should have_selector "tr#li_#{li2.id}", visible: true + select oc1.name, from: "order_cycle_filter" + page.should have_selector "tr#li_#{li1.id}", visible: true + page.should_not have_selector "tr#li_#{li2.id}", visible: true + end + + it "displays all line items when 'All' is selected from order_cycle filter" do + select oc1.name, from: "order_cycle_filter" + page.should have_selector "tr#li_#{li1.id}", visible: true + page.should_not have_selector "tr#li_#{li2.id}", visible: true + select "All", from: "order_cycle_filter" + page.should have_selector "tr#li_#{li1.id}", visible: true + page.should have_selector "tr#li_#{li2.id}", visible: true + end end context "using date restriction controls" do diff --git a/spec/javascripts/unit/bulk_order_management_spec.js.coffee b/spec/javascripts/unit/bulk_order_management_spec.js.coffee index 52c4dfef05..3e291a6d19 100644 --- a/spec/javascripts/unit/bulk_order_management_spec.js.coffee +++ b/spec/javascripts/unit/bulk_order_management_spec.js.coffee @@ -13,22 +13,29 @@ describe "AdminOrderMgmtCtrl", -> ) describe "loading data upon initialisation", -> - it "gets a list of suppliers and a list of distributors and then calls fetchOrders", -> + it "gets a list of suppliers, a list of distributors and a list of Order Cycles and then calls fetchOrders", -> returnedSuppliers = ["list of suppliers"] returnedDistributors = ["list of distributors"] + returnedOrderCycles = [ "oc1", "oc2", "oc3" ] httpBackend.expectGET("/api/users/authorise_api?token=api_key").respond success: "Use of API Authorised" httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_primary_producer_eq]=true").respond returnedSuppliers httpBackend.expectGET("/api/enterprises/managed?template=bulk_index&q[is_distributor_eq]=true").respond returnedDistributors + httpBackend.expectGET("/api/order_cycles/managed").respond returnedOrderCycles spyOn(scope, "fetchOrders").andReturn "nothing" spyOn(returnedSuppliers, "unshift") spyOn(returnedDistributors, "unshift") + spyOn(returnedOrderCycles, "unshift") + spyOn(scope, "matchOrderCycleEnterprises") scope.initialise "api_key" httpBackend.flush() expect(scope.suppliers).toEqual ["list of suppliers"] expect(scope.distributors).toEqual ["list of distributors"] + expect(scope.orderCycles).toEqual [ "oc1", "oc2", "oc3" ] expect(scope.fetchOrders.calls.length).toEqual 1 expect(returnedSuppliers.unshift.calls.length).toEqual 1 expect(returnedDistributors.unshift.calls.length).toEqual 1 + expect(returnedOrderCycles.unshift.calls.length).toEqual 1 + expect(scope.matchOrderCycleEnterprises.calls.length).toEqual returnedOrderCycles.length expect(scope.spree_api_key_ok).toEqual true describe "fetching orders", -> @@ -53,7 +60,7 @@ describe "AdminOrderMgmtCtrl", -> describe "resetting orders", -> beforeEach -> - spyOn(scope, "matchDistributor").andReturn "nothing" + spyOn(scope, "matchObject").andReturn "nothing" spyOn(scope, "resetLineItems").andReturn "nothing" scope.resetOrders [ "order1", "order2", "order3" ] @@ -63,14 +70,14 @@ describe "AdminOrderMgmtCtrl", -> it "makes a call to $scope.resetLineItems", -> expect(scope.resetLineItems).toHaveBeenCalled() - it "calls matchDistributor for each line item", -> - expect(scope.matchDistributor.calls.length).toEqual 3 + it "calls matchObject twice for each order (once for distributor and once for order cycle)", -> + expect(scope.matchObject.calls.length).toEqual scope.orders.length * 2 describe "resetting line items", -> order1 = order2 = order3 = null beforeEach -> - spyOn(scope, "matchSupplier").andReturn "nothing" + spyOn(scope, "matchObject").andReturn "nothing" order1 = { line_items: [ { name: "line_item1.1" }, { name: "line_item1.1" }, { name: "line_item1.1" } ] } order2 = { line_items: [ { name: "line_item2.1" }, { name: "line_item2.1" }, { name: "line_item2.1" } ] } order3 = { line_items: [ { name: "line_item3.1" }, { name: "line_item3.1" }, { name: "line_item3.1" } ] } @@ -88,60 +95,78 @@ describe "AdminOrderMgmtCtrl", -> expect(scope.lineItems[3].order).toEqual order2 expect(scope.lineItems[6].order).toEqual order3 - it "calls matchSupplier for each line item", -> - expect(scope.matchSupplier.calls.length).toEqual 9 + it "calls matchObject once for each line item", -> + expect(scope.matchObject.calls.length).toEqual scope.lineItems.length - describe "matching supplier", -> - it "changes the supplier of the line_item to the one which matches it from the suppliers list", -> - supplier1_list = + describe "matching objects", -> + it "returns the first matching object in the list", -> + list_item1 = id: 1 - name: "S1" + name: "LI1" - supplier2_list = + list_item2 = id: 2 - name: "S2" + name: "LI2" - supplier1_line_item = - id: 1 - name: "S1" - - expect(supplier1_list is supplier1_line_item).not.toEqual true - scope.suppliers = [ - supplier1_list - supplier2_list - ] - line_item = - id: 10 - supplier: supplier1_line_item - - scope.matchSupplier line_item - expect(line_item.supplier is supplier1_list).toEqual true - - describe "matching distributor", -> - it "changes the distributor of the order to the one which matches it from the distributors list", -> - distributor1_list = - id: 1 - name: "D1" - - distributor2_list = + test_item = id: 2 - name: "D2" + name: "LI2" - distributor1_order = - id: 1 - name: "D1" - - expect(distributor1_list is distributor1_order).not.toEqual true - scope.distributors = [ - distributor1_list - distributor2_list + expect(list_item2 is test_item).not.toEqual true + list = [ + list_item1 + list_item2 ] - order = - id: 10 - distributor: distributor1_order - scope.matchDistributor order - expect(order.distributor is distributor1_list).toEqual true + returned_item = scope.matchObject list, test_item, null + expect(returned_item is list_item2).toEqual true + + it "returns the default provided if no matching item is found", -> + list_item1 = + id: 1 + name: "LI1" + + list_item2 = + id: 2 + name: "LI2" + + test_item = + id: 1 + name: "LI2" + + expect(list_item2 is test_item).not.toEqual true + list = [ + list_item1 + list_item2 + ] + + returned_item = scope.matchObject list, test_item, null + expect(returned_item is null).toEqual true + + describe "matching order cycles enterprises", -> + it "calls matchDistributor once for each distributor associated with an order cycle", -> + spyOn(scope, "matchObject") + distributors = [ + "distributor1" + "distributor2" + "distributor3" + ] + suppliers = [] + orderCycle = { distributors: distributors } + scope.matchOrderCycleEnterprises orderCycle + expect(scope.matchObject.calls.length).toEqual 3 + + it "calls matchSupplier once for each distributor associated with an order cycle", -> + spyOn(scope, "matchObject") + distributors = [] + suppliers = [ + "supplier1" + "supplier2" + "supplier3" + ] + orderCycle = { suppliers: suppliers } + scope.matchOrderCycleEnterprises orderCycle + expect(scope.matchObject.calls.length).toEqual 3 describe "deleting a line item", -> order = line_item1 = line_item2 = null