mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-12 23:27:48 +00:00
Merge pull request #5099 from Matt-Yorkley/ticking-time-bom
Improve BOM
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, StatusMessage, Columns, SortOptions, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, VariantUnitManager, RequestMonitor) ->
|
||||
$scope.initialized = false
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.filteredLineItems = []
|
||||
$scope.line_items = LineItems.all
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
|
||||
$scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
|
||||
@@ -15,50 +15,77 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.resetFilters = ->
|
||||
$scope.distributorFilter = ''
|
||||
$scope.supplierFilter = ''
|
||||
$scope.orderCycleFilter = ''
|
||||
$scope.quickSearch = ''
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.distributorFilter = 0
|
||||
$scope.supplierFilter = 0
|
||||
$scope.orderCycleFilter = 0
|
||||
$scope.quickSearch = ""
|
||||
$scope.resetFilters()
|
||||
$scope.refreshData()
|
||||
|
||||
$scope.refreshData = ->
|
||||
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0
|
||||
$scope.startDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_open_at).format('YYYY-MM-DD')
|
||||
$scope.endDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_close_at).startOf('day').format('YYYY-MM-DD')
|
||||
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == ''
|
||||
$scope.setOrderCycleDateRange()
|
||||
|
||||
formatted_start_date = moment($scope.startDate).format()
|
||||
formatted_end_date = moment($scope.endDate).add(1,'day').format()
|
||||
$scope.formattedStartDate = moment($scope.startDate).format()
|
||||
$scope.formattedEndDate = moment($scope.endDate).add(1,'day').format()
|
||||
|
||||
return unless moment($scope.formattedStartDate).isValid() and moment($scope.formattedEndDate).isValid()
|
||||
|
||||
$scope.loadOrders()
|
||||
$scope.loadLineItems()
|
||||
|
||||
unless $scope.initialized
|
||||
$scope.loadAssociatedData()
|
||||
|
||||
$scope.dereferenceLoadedData()
|
||||
|
||||
$scope.setOrderCycleDateRange = ->
|
||||
start_date = OrderCycles.byID[$scope.orderCycleFilter].orders_open_at
|
||||
end_date = OrderCycles.byID[$scope.orderCycleFilter].orders_close_at
|
||||
format = "YYYY-MM-DD HH:mm:ss Z"
|
||||
$scope.startDate = moment(start_date, format).format('YYYY-MM-DD')
|
||||
$scope.endDate = moment(end_date, format).startOf('day').format('YYYY-MM-DD')
|
||||
|
||||
$scope.loadOrders = ->
|
||||
RequestMonitor.load $scope.orders = Orders.index(
|
||||
"q[state_not_eq]": "canceled",
|
||||
"q[completed_at_not_null]": "true",
|
||||
"q[completed_at_gteq]": formatted_start_date,
|
||||
"q[completed_at_lt]": formatted_end_date
|
||||
"q[distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
"q[completed_at_gteq]": $scope.formattedStartDate,
|
||||
"q[completed_at_lt]": $scope.formattedEndDate
|
||||
)
|
||||
|
||||
RequestMonitor.load $scope.lineItems = LineItems.index(
|
||||
"q[order][state_not_eq]": "canceled",
|
||||
"q[order][completed_at_not_null]": "true",
|
||||
"q[order][completed_at_gteq]": formatted_start_date,
|
||||
"q[order][completed_at_lt]": formatted_end_date
|
||||
$scope.loadLineItems = ->
|
||||
RequestMonitor.load LineItems.index(
|
||||
"q[order_state_not_eq]": "canceled",
|
||||
"q[order_completed_at_not_null]": "true",
|
||||
"q[order_distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[variant_product_supplier_id_eq]": $scope.supplierFilter,
|
||||
"q[order_order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
"q[order_completed_at_gteq]": $scope.formattedStartDate,
|
||||
"q[order_completed_at_lt]": $scope.formattedEndDate
|
||||
)
|
||||
|
||||
unless $scope.initialized
|
||||
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
$scope.loadAssociatedData = ->
|
||||
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise, $scope.suppliers.$promise, $scope.lineItems.$promise]).then ->
|
||||
$scope.dereferenceLoadedData = ->
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise, $scope.suppliers.$promise, $scope.line_items.$promise]).then ->
|
||||
Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.orders, "order_cycle", OrderCycles.byID
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "supplier", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "order", Orders.byID
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "supplier", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "order", Orders.byID
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
StatusMessage.clear()
|
||||
|
||||
unless $scope.initialized
|
||||
$scope.initialized = true
|
||||
$timeout ->
|
||||
$scope.resetSelectFilters()
|
||||
|
||||
$scope.$watch 'bulk_order_form.$dirty', (newVal, oldVal) ->
|
||||
if newVal == true
|
||||
@@ -77,13 +104,12 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
|
||||
$scope.deleteLineItem = (lineItem) ->
|
||||
if ($scope.confirmDelete && confirm(t "are_you_sure")) || !$scope.confirmDelete
|
||||
LineItems.delete lineItem, =>
|
||||
$scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1
|
||||
LineItems.delete lineItem
|
||||
|
||||
$scope.deleteLineItems = (lineItems) ->
|
||||
$scope.deleteLineItems = (lineItemsToDelete) ->
|
||||
existingState = $scope.confirmDelete
|
||||
$scope.confirmDelete = false
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItemsToDelete when lineItem.checked
|
||||
$scope.confirmDelete = existingState
|
||||
|
||||
$scope.allBoxesChecked = ->
|
||||
@@ -154,4 +180,5 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
lineItem.final_weight_volume = LineItems.pristineByID[lineItem.id].final_weight_volume * lineItem.quantity / LineItems.pristineByID[lineItem.id].quantity
|
||||
$scope.weightAdjustedPrice(lineItem)
|
||||
|
||||
$scope.resetFilters()
|
||||
$scope.refreshData()
|
||||
|
||||
@@ -2,7 +2,6 @@ angular.module("admin.resources").factory 'LineItemResource', ($resource) ->
|
||||
$resource('/admin/bulk_line_items/:id.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
'update':
|
||||
method: 'PUT'
|
||||
transformRequest: (data, headersGetter) =>
|
||||
|
||||
@@ -1,20 +1,27 @@
|
||||
angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
|
||||
new class LineItems
|
||||
all: []
|
||||
byID: {}
|
||||
pristineByID: {}
|
||||
pagination: {}
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
LineItemResource.index params, (data) =>
|
||||
request = LineItemResource.index params, (data) =>
|
||||
@load(data)
|
||||
(callback || angular.noop)(data)
|
||||
@all.$promise = request.$promise
|
||||
@all
|
||||
|
||||
resetData: ->
|
||||
@all.length = 0
|
||||
@byID = {}
|
||||
@pristineByID = {}
|
||||
|
||||
load: (lineItems) ->
|
||||
load: (data) ->
|
||||
angular.extend(@pagination, data.pagination)
|
||||
@resetData()
|
||||
for lineItem in lineItems
|
||||
for lineItem in data.line_items
|
||||
@all.push lineItem
|
||||
@byID[lineItem.id] = lineItem
|
||||
@pristineByID[lineItem.id] = angular.copy(lineItem)
|
||||
|
||||
@@ -25,8 +32,9 @@ angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
|
||||
|
||||
save: (lineItem) ->
|
||||
deferred = $q.defer()
|
||||
lineItemResource = new LineItemResource(lineItem)
|
||||
lineItem.errors = {}
|
||||
lineItem.$update({id: lineItem.id})
|
||||
lineItemResource.$update({id: lineItem.id})
|
||||
.then( (data) =>
|
||||
@pristineByID[lineItem.id] = angular.copy(lineItem)
|
||||
deferred.resolve(data)
|
||||
@@ -54,8 +62,10 @@ angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
|
||||
|
||||
delete: (lineItem, callback=null) ->
|
||||
deferred = $q.defer()
|
||||
lineItem.$delete({id: lineItem.id})
|
||||
lineItemResource = new LineItemResource(lineItem)
|
||||
lineItemResource.$delete({id: lineItem.id})
|
||||
.then( (data) =>
|
||||
@all.splice(@all.indexOf(lineItem),1)
|
||||
delete @byID[lineItem.id]
|
||||
delete @pristineByID[lineItem.id]
|
||||
(callback || angular.noop)(data)
|
||||
|
||||
@@ -4,18 +4,17 @@ module Admin
|
||||
#
|
||||
def index
|
||||
order_params = params[:q].andand.delete :order
|
||||
orders = order_permissions.editable_orders.ransack(order_params).result
|
||||
|
||||
order_permissions = ::Permissions::Order.new(spree_current_user)
|
||||
orders = order_permissions.
|
||||
editable_orders.ransack(order_params).result
|
||||
|
||||
line_items = order_permissions.
|
||||
@line_items = order_permissions.
|
||||
editable_line_items.where(order_id: orders).
|
||||
includes(variant: { option_values: :option_type }).
|
||||
ransack(params[:q]).result.
|
||||
reorder('spree_line_items.order_id ASC, spree_line_items.id ASC')
|
||||
|
||||
render_as_json line_items
|
||||
@line_items = @line_items.page(page).per(params[:per_page]) if using_pagination?
|
||||
|
||||
render json: { line_items: serialized_line_items, pagination: pagination_data }
|
||||
end
|
||||
|
||||
# PUT /admin/bulk_line_items/:id.json
|
||||
@@ -65,6 +64,12 @@ module Admin
|
||||
Api::Admin::LineItemSerializer
|
||||
end
|
||||
|
||||
def serialized_line_items
|
||||
ActiveModel::ArraySerializer.new(
|
||||
@line_items, each_serializer: serializer(nil)
|
||||
)
|
||||
end
|
||||
|
||||
def authorize_update!
|
||||
authorize! :update, order
|
||||
authorize! :read, order
|
||||
@@ -73,5 +78,28 @@ module Admin
|
||||
def order
|
||||
@line_item.order
|
||||
end
|
||||
|
||||
def order_permissions
|
||||
::Permissions::Order.new(spree_current_user)
|
||||
end
|
||||
|
||||
def using_pagination?
|
||||
params[:per_page]
|
||||
end
|
||||
|
||||
def pagination_data
|
||||
return unless using_pagination?
|
||||
|
||||
{
|
||||
results: @line_items.total_count,
|
||||
pages: @line_items.num_pages,
|
||||
page: page.to_i,
|
||||
per_page: params[:per_page].to_i
|
||||
}
|
||||
end
|
||||
|
||||
def page
|
||||
params[:page] || 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,28 +20,28 @@
|
||||
%label{ :for => 'start_date_filter' }
|
||||
= t("admin.start_date")
|
||||
%br
|
||||
%input{ :class => "two columns alpha", :type => "text", :id => 'start_date_filter', 'ng-model' => 'startDate', 'datepicker' => "startDate", 'confirm-change' => "confirmRefresh()", 'ng-change' => 'refreshData()' }
|
||||
%input{ :class => "two columns alpha", :type => "text", :id => 'start_date_filter', 'ng-model' => 'startDate', 'datepicker' => "startDate", 'confirm-change' => "confirmRefresh()", 'ng-change' => 'refreshData()', 'ng-model-options' => '{ debounce: 1000 }' }
|
||||
.date_filter{ :class => "two columns" }
|
||||
%label{ :for => 'end_date_filter' }
|
||||
= t("admin.end_date")
|
||||
%br
|
||||
%input{ :class => "two columns alpha", :type => "text", :id => 'end_date_filter', 'ng-model' => 'endDate', 'datepicker' => "endDate", 'confirm-change' => "confirmRefresh()", 'ng-change' => 'refreshData()' }
|
||||
%input{ :class => "two columns alpha", :type => "text", :id => 'end_date_filter', 'ng-model' => 'endDate', 'datepicker' => "endDate", 'confirm-change' => "confirmRefresh()", 'ng-change' => 'refreshData()', 'ng-model-options' => '{ debounce: 1000 }' }
|
||||
.one.column
|
||||
.filter_select{ :class => "three columns" }
|
||||
%label{ :for => 'supplier_filter' }
|
||||
= t("admin.producer")
|
||||
%br
|
||||
%input#supplier_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'suppliers', blank: "{ id: 0, name: '#{t(:all)}' }", ng: { model: 'supplierFilter' } }
|
||||
%input#supplier_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'suppliers', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'supplierFilter', change: 'refreshData()' } }
|
||||
.filter_select{ :class => "three columns" }
|
||||
%label{ :for => 'distributor_filter' }
|
||||
= t("admin.shop")
|
||||
%br
|
||||
%input#distributor_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'distributors', blank: "{ id: 0, name: '#{t(:all)}' }", ng: { model: 'distributorFilter' } }
|
||||
%input#distributor_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'distributors', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'distributorFilter', change: 'refreshData()' } }
|
||||
.filter_select{ :class => "three columns" }
|
||||
%label{ :for => 'order_cycle_filter' }
|
||||
= t("admin.order_cycle")
|
||||
%br
|
||||
%input#order_cycle_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'orderCycles', blank: "{ id: 0, name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'orderCycleFilter', change: 'refreshData()' } }
|
||||
%input#order_cycle_filter.ofn-select2.fullwidth{ type: 'number', 'min-search' => 5, data: 'orderCycles', placeholder: "#{t(:all)}", blank: "{ id: '', name: '#{t(:all)}' }", on: { selecting: "confirmRefresh" }, ng: { model: 'orderCycleFilter', change: 'refreshData()' } }
|
||||
.filter_clear{ :class => "two columns omega" }
|
||||
%label{ :for => 'clear_all_filters' }
|
||||
%br
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
%hr.divider.sixteen.columns.alpha.omega
|
||||
|
||||
.controls.sixteen.columns.alpha.omega{ ng: { hide: 'RequestMonitor.loading || lineItems.length == 0' } }
|
||||
.controls.sixteen.columns.alpha.omega{ ng: { hide: 'RequestMonitor.loading || line_items.length == 0' } }
|
||||
%div.three.columns.alpha
|
||||
%input.fullwidth{ :type => "text", :id => 'quick_search', 'ng-model' => 'quickSearch', :placeholder => 'Quick Search' }
|
||||
= render 'admin/shared/bulk_actions_dropdown'
|
||||
@@ -157,7 +157,7 @@
|
||||
= t("admin.orders.bulk_management.ask")
|
||||
%input{ :type => 'checkbox', 'ng-model' => "confirmDelete" }
|
||||
|
||||
%tr.line_item{ ng: { repeat: "line_item in filteredLineItems = ( lineItems | filter:quickSearch | selectFilter:supplierFilter:distributorFilter:orderCycleFilter | variantFilter:selectedUnitsProduct:selectedUnitsVariant:sharedResource | orderBy:sorting.predicate:sorting.reverse )", 'class-even' => "'even'", 'class-odd' => "'odd'", attr: { id: "li_{{line_item.id}}" } } }
|
||||
%tr.line_item{ ng: { repeat: "line_item in filteredLineItems = ( line_items | filter:quickSearch | variantFilter:selectedUnitsProduct:selectedUnitsVariant:sharedResource | orderBy:sorting.predicate:sorting.reverse )", 'class-even' => "'even'", 'class-odd' => "'odd'", attr: { id: "li_{{line_item.id}}" } } }
|
||||
%td.bulk
|
||||
%input{ :type => "checkbox", :name => 'bulk', 'ng-model' => 'line_item.checked', 'ignore-dirty' => true }
|
||||
%td.order_no{ 'ng-show' => 'columns.order_no.visible' } {{ line_item.order.number }}
|
||||
@@ -175,7 +175,7 @@
|
||||
%span.error{ ng: { bind: 'line_item.errors.quantity' } }
|
||||
%td.max{ 'ng-show' => 'columns.max.visible' } {{ line_item.max_quantity }}
|
||||
%td.final_weight_volume{ 'ng-show' => 'columns.final_weight_volume.visible' }
|
||||
%input.show-dirty{ :type => 'number', :name => 'final_weight_volume', :id => 'final_weight_volume', ng: { model: "line_item.final_weight_volume", readonly: "unitValueLessThanZero(line_item)", change: "weightAdjustedPrice(line_item)", required: "true", class: '{"update-error": line_item.errors.final_weight_volume}' }, min: 0, 'ng-pattern' => '/[1-9]+/' }
|
||||
%input.show-dirty{ type: 'number', step: 'any', :name => 'final_weight_volume', :id => 'final_weight_volume', ng: { model: "line_item.final_weight_volume", readonly: "unitValueLessThanZero(line_item)", change: "weightAdjustedPrice(line_item)", required: "true", class: '{"update-error": line_item.errors.final_weight_volume}' }, min: 0, 'ng-pattern' => '/[0-9]*[.]?[0-9]+/' }
|
||||
%span.error{ ng: { bind: 'line_item.errors.final_weight_volume' } }
|
||||
%td.price{ 'ng-show' => 'columns.price.visible' }
|
||||
%input.show-dirty{ :type => 'text', :name => 'price', :id => 'price', :ng => { value: 'line_item.price * line_item.quantity | currency:""', readonly: "true", class: '{"update-error": line_item.errors.price}' } }
|
||||
|
||||
@@ -36,22 +36,21 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
it "retrieves a list of line_items with appropriate attributes, including line items with appropriate attributes" do
|
||||
keys = json_response.first.keys.map(&:to_sym)
|
||||
keys = json_response['line_items'].first.keys.map(&:to_sym)
|
||||
expect(line_item_attributes.all?{ |attr| keys.include? attr }).to eq(true)
|
||||
end
|
||||
|
||||
it "sorts line_items in ascending id line_item" do
|
||||
ids = json_response.map{ |line_item| line_item['id'] }
|
||||
expect(ids[0]).to be < ids[1]
|
||||
expect(ids[1]).to be < ids[2]
|
||||
expect(line_item_ids[0]).to be < line_item_ids[1]
|
||||
expect(line_item_ids[1]).to be < line_item_ids[2]
|
||||
end
|
||||
|
||||
it "formats final_weight_volume as a float" do
|
||||
expect(json_response.map{ |line_item| line_item['final_weight_volume'] }.all?{ |fwv| fwv.is_a?(Float) }).to eq(true)
|
||||
expect(json_response['line_items'].map{ |line_item| line_item['final_weight_volume'] }.all?{ |fwv| fwv.is_a?(Float) }).to eq(true)
|
||||
end
|
||||
|
||||
it "returns distributor object with id key" do
|
||||
expect(json_response.map{ |line_item| line_item['supplier'] }.all?{ |d| d.key?('id') }).to eq(true)
|
||||
expect(json_response['line_items'].map{ |line_item| line_item['supplier'] }.all?{ |d| d.key?('id') }).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -61,7 +60,7 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
it "retrives a list of line items which match the criteria" do
|
||||
expect(json_response.map{ |line_item| line_item['id'] }).to eq [line_item2.id, line_item3.id]
|
||||
expect(line_item_ids).to eq [line_item2.id, line_item3.id]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -71,7 +70,7 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
it "retrives a list of line items whose orders match the criteria" do
|
||||
expect(json_response.map{ |line_item| line_item['id'] }).to eq [line_item2.id, line_item3.id, line_item4.id]
|
||||
expect(line_item_ids).to eq [line_item2.id, line_item3.id, line_item4.id]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -106,7 +105,7 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
it "retrieves a list of line_items" do
|
||||
keys = json_response.first.keys.map(&:to_sym)
|
||||
keys = json_response['line_items'].first.keys.map(&:to_sym)
|
||||
expect(line_item_attributes.all?{ |attr| keys.include? attr }).to eq(true)
|
||||
end
|
||||
end
|
||||
@@ -118,11 +117,37 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
it "retrieves a list of line_items" do
|
||||
keys = json_response.first.keys.map(&:to_sym)
|
||||
keys = json_response['line_items'].first.keys.map(&:to_sym)
|
||||
expect(line_item_attributes.all?{ |attr| keys.include? attr }).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "paginating" do
|
||||
before do
|
||||
allow(controller).to receive_messages spree_current_user: create(:admin_user)
|
||||
end
|
||||
|
||||
context "with pagination args" do
|
||||
it "returns paginated results" do
|
||||
spree_get :index, { page: 1, per_page: 2 }, format: :json
|
||||
|
||||
expect(line_item_ids).to eq [line_item1.id, line_item2.id]
|
||||
expect(json_response['pagination']).to eq(
|
||||
{ 'page' => 1, 'per_page' => 2, 'pages' => 2, 'results' => 4 }
|
||||
)
|
||||
end
|
||||
|
||||
it "returns paginated results for a second page" do
|
||||
spree_get :index, { page: 2, per_page: 2 }, format: :json
|
||||
|
||||
expect(line_item_ids).to eq [line_item3.id, line_item4.id]
|
||||
expect(json_response['pagination']).to eq(
|
||||
{ 'page' => 2, 'per_page' => 2, 'pages' => 2, 'results' => 4 }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#update' do
|
||||
@@ -259,4 +284,10 @@ describe Admin::BulkLineItemsController, type: :controller do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def line_item_ids
|
||||
json_response['line_items'].map{ |line_item| line_item['id'] }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -494,7 +494,7 @@ feature '
|
||||
|
||||
it "shows a dialog and ignores changes when confirm dialog is accepted" do
|
||||
page.driver.accept_modal :confirm, text: "Unsaved changes exist and will be lost if you continue." do
|
||||
fill_in "start_date_filter", with: (Date.current - 9).strftime("%F %T")
|
||||
fill_in "start_date_filter", with: (Date.current - 9).strftime('%Y-%m-%d')
|
||||
end
|
||||
expect(page).to have_no_selector "#save-bar"
|
||||
within("tr#li_#{li2.id} td.quantity") do
|
||||
@@ -577,6 +577,7 @@ feature '
|
||||
find("div#bulk-actions-dropdown").click
|
||||
find("div#bulk-actions-dropdown div.menu_item", text: "Delete Selected" ).click
|
||||
expect(page).to have_no_selector "tr#li_#{li1.id}"
|
||||
expect(page).to have_selector "#quick_search"
|
||||
fill_in "quick_search", with: ''
|
||||
wait_until { request_monitor_finished 'LineItemsCtrl' }
|
||||
expect(page).to have_selector "tr#li_#{li2.id}"
|
||||
|
||||
@@ -13,23 +13,23 @@ describe "LineItemsCtrl", ->
|
||||
compare: (actual, expected) ->
|
||||
{ pass: angular.equals(actual, expected) }
|
||||
|
||||
beforeEach inject(($controller, $rootScope, $httpBackend, _$timeout_, _VariantUnitManager_, _Enterprises_, _Orders_, _LineItems_, _OrderCycles_) ->
|
||||
beforeEach inject(($controller, $rootScope, $httpBackend, _$timeout_, _VariantUnitManager_, _Enterprises_, _Orders_, _OrderCycles_) ->
|
||||
scope = $rootScope.$new()
|
||||
ctrl = $controller
|
||||
$timeout = _$timeout_
|
||||
httpBackend = $httpBackend
|
||||
Enterprises = _Enterprises_
|
||||
Orders = _Orders_
|
||||
LineItems = _LineItems_
|
||||
OrderCycles = _OrderCycles_
|
||||
VariantUnitManager = _VariantUnitManager_
|
||||
momentMock = jasmine.createSpyObj('moment', ['format', 'startOf', 'endOf', 'subtract', 'add'])
|
||||
momentMock = jasmine.createSpyObj('moment', ['format', 'startOf', 'endOf', 'subtract', 'add', 'isValid'])
|
||||
spyOn(window,"moment").and.returnValue momentMock
|
||||
momentMock.startOf.and.returnValue momentMock
|
||||
momentMock.endOf.and.returnValue momentMock
|
||||
momentMock.subtract.and.returnValue momentMock
|
||||
momentMock.add.and.returnValue momentMock
|
||||
momentMock.format.and.returnValue "SomeDate"
|
||||
momentMock.isValid.and.returnValue true
|
||||
|
||||
supplier = { id: 1, name: "Supplier" }
|
||||
distributor = { id: 5, name: "Distributor" }
|
||||
@@ -37,8 +37,11 @@ describe "LineItemsCtrl", ->
|
||||
order = { id: 9, order_cycle: { id: 4 }, distributor: { id: 5 }, number: "R123456" }
|
||||
lineItem = { id: 7, quantity: 3, order: { id: 9 }, supplier: { id: 1 } }
|
||||
|
||||
httpBackend.expectGET("/api/orders.json?q%5Bcompleted_at_gteq%5D=SomeDate&q%5Bcompleted_at_lt%5D=SomeDate&q%5Bcompleted_at_not_null%5D=true&q%5Bstate_not_eq%5D=canceled").respond {orders: [order], pagination: {page: 1, pages: 1, results: 1}}
|
||||
httpBackend.expectGET("/admin/bulk_line_items.json?q%5Border%5D%5Bcompleted_at_gteq%5D=SomeDate&q%5Border%5D%5Bcompleted_at_lt%5D=SomeDate&q%5Border%5D%5Bcompleted_at_not_null%5D=true&q%5Border%5D%5Bstate_not_eq%5D=canceled").respond [lineItem]
|
||||
LineItems =
|
||||
index: jasmine.createSpy('index').and.returnValue(lineItem)
|
||||
all: [lineItem]
|
||||
|
||||
httpBackend.expectGET("/api/orders.json?q%5Bcompleted_at_gteq%5D=SomeDate&q%5Bcompleted_at_lt%5D=SomeDate&q%5Bcompleted_at_not_null%5D=true&q%5Bdistributor_id_eq%5D=&q%5Border_cycle_id_eq%5D=&q%5Bstate_not_eq%5D=canceled").respond {orders: [order], pagination: {page: 1, pages: 1, results: 1}}
|
||||
httpBackend.expectGET("/admin/enterprises/visible.json?ams_prefix=basic&q%5Bsells_in%5D%5B%5D=own&q%5Bsells_in%5D%5B%5D=any").respond [distributor]
|
||||
httpBackend.expectGET("/admin/order_cycles.json?ams_prefix=basic&as=distributor&q%5Borders_close_at_gt%5D=SomeDate").respond [orderCycle]
|
||||
httpBackend.expectGET("/admin/enterprises/visible.json?ams_prefix=basic&q%5Bis_primary_producer_eq%5D=true").respond [supplier]
|
||||
@@ -52,12 +55,6 @@ describe "LineItemsCtrl", ->
|
||||
it "the RequestMonitor will have a state of loading", ->
|
||||
expect(scope.RequestMonitor.loading).toBe true
|
||||
|
||||
it "will not have reset the select filters", ->
|
||||
expect(scope.distributorFilter).toBeUndefined()
|
||||
expect(scope.supplierFilter).toBeUndefined()
|
||||
expect(scope.orderCycleFilter).toBeUndefined()
|
||||
expect(scope.quickSearch).toBeUndefined()
|
||||
|
||||
it "will not have reset the form state to pristine", ->
|
||||
expect(scope.bulk_order_form.$setPristine.calls.count()).toBe 0
|
||||
|
||||
@@ -83,49 +80,20 @@ describe "LineItemsCtrl", ->
|
||||
expect(scope.orders).toDeepEqual [ { id: 9, order_cycle: orderCycle, distributor: distributor, number: "R123456" } ]
|
||||
|
||||
it "gets line_items, with dereferenced orders and suppliers", ->
|
||||
expect(scope.lineItems).toDeepEqual [ { id: 7, quantity: 3, order: scope.orders[0], supplier: supplier } ]
|
||||
expect(scope.line_items).toDeepEqual [ { id: 7, quantity: 3, order: scope.orders[0], supplier: supplier } ]
|
||||
|
||||
it "the RequestMonitor will have a state of loaded", ->
|
||||
expect(scope.RequestMonitor.loading).toBe false
|
||||
|
||||
it "resets the select filters", ->
|
||||
expect(scope.distributorFilter).toBe 0
|
||||
expect(scope.supplierFilter).toBe 0
|
||||
expect(scope.orderCycleFilter).toBe 0
|
||||
expect(scope.distributorFilter).toBe ''
|
||||
expect(scope.supplierFilter).toBe ''
|
||||
expect(scope.orderCycleFilter).toBe ''
|
||||
expect(scope.quickSearch).toBe = ""
|
||||
|
||||
it "resets the form state to pristine", ->
|
||||
expect(scope.bulk_order_form.$setPristine.calls.count()).toBe 1
|
||||
|
||||
describe "deleting a line item", ->
|
||||
order = line_item1 = line_item2 = null
|
||||
|
||||
beforeEach inject((LineItemResource) ->
|
||||
spyOn(window,"confirm").and.returnValue true
|
||||
order = { number: "R12345678" }
|
||||
line_item1 = new LineItemResource({ id: 1, order: order })
|
||||
line_item2 = new LineItemResource({ id: 2, order: order })
|
||||
scope.lineItems= [ line_item1, line_item2 ]
|
||||
)
|
||||
|
||||
describe "where the request is successful", ->
|
||||
beforeEach ->
|
||||
httpBackend.expectDELETE("/admin/bulk_line_items/1.json").respond "nothing"
|
||||
scope.deleteLineItem line_item1
|
||||
httpBackend.flush()
|
||||
|
||||
it "removes the deleted item from the line_items array", ->
|
||||
expect(scope.lineItems).toEqual [line_item2]
|
||||
|
||||
describe "where the request is unsuccessful", ->
|
||||
beforeEach ->
|
||||
httpBackend.expectDELETE("/admin/bulk_line_items/1.json").respond 404, "NO CONTENT"
|
||||
scope.deleteLineItem line_item1
|
||||
httpBackend.flush()
|
||||
|
||||
it "does not remove line_item from the line_items array", ->
|
||||
expect(scope.lineItems).toEqual [line_item1, line_item2]
|
||||
|
||||
describe "deleting 'checked' line items", ->
|
||||
line_item1 = line_item2 = line_item3 = line_item4 = null
|
||||
|
||||
@@ -134,11 +102,11 @@ describe "LineItemsCtrl", ->
|
||||
line_item2 = { name: "line item 2", checked: true }
|
||||
line_item3 = { name: "line item 3", checked: false }
|
||||
line_item4 = { name: "line item 4", checked: true }
|
||||
scope.lineItems = [ line_item1, line_item2, line_item3, line_item4 ]
|
||||
scope.line_items = [ line_item1, line_item2, line_item3, line_item4 ]
|
||||
|
||||
it "calls deletedLineItem for each 'checked' line item", ->
|
||||
spyOn(scope, "deleteLineItem")
|
||||
scope.deleteLineItems(scope.lineItems)
|
||||
scope.deleteLineItems(scope.line_items)
|
||||
expect(scope.deleteLineItem).toHaveBeenCalledWith(line_item2)
|
||||
expect(scope.deleteLineItem).toHaveBeenCalledWith(line_item4)
|
||||
expect(scope.deleteLineItem).not.toHaveBeenCalledWith(line_item1)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
describe "LineItems service", ->
|
||||
LineItems = LineItemResource = lineItems = $httpBackend = null
|
||||
LineItems = LineItemResource = lineItems = $httpBackend = $rootScope = $timeout = null
|
||||
|
||||
beforeEach ->
|
||||
module 'admin.lineItems'
|
||||
@@ -15,24 +15,27 @@ describe "LineItems service", ->
|
||||
$httpBackend = _$httpBackend_
|
||||
|
||||
describe "#index", ->
|
||||
result = response = null
|
||||
result = response = line_item = null
|
||||
|
||||
beforeEach ->
|
||||
response = [{ id: 5, name: 'LineItem 1'}]
|
||||
line_item = { id: 5, name: 'LineItem 1'}
|
||||
response = { line_items: [line_item] }
|
||||
$httpBackend.expectGET('/admin/bulk_line_items.json').respond 200, response
|
||||
result = LineItems.index()
|
||||
$httpBackend.flush()
|
||||
|
||||
it "stores returned data in @byID, with ids as keys", ->
|
||||
# LineItemResource returns instances of Resource rather than raw objects
|
||||
expect(LineItems.byID).toDeepEqual { 5: response[0] }
|
||||
expect(LineItems.byID).toDeepEqual { 5: response['line_items'][0] }
|
||||
|
||||
it "stores returned data in @pristineByID, with ids as keys", ->
|
||||
expect(LineItems.pristineByID).toDeepEqual { 5: response[0] }
|
||||
expect(LineItems.pristineByID).toDeepEqual { 5: response['line_items'][0] }
|
||||
|
||||
it "stores returned data in @all, as an array", ->
|
||||
expect(LineItems.all).toDeepEqual [line_item]
|
||||
|
||||
it "returns an array of line items", ->
|
||||
expect(result).toDeepEqual response
|
||||
|
||||
expect(result).toDeepEqual [line_item]
|
||||
|
||||
describe "#save", ->
|
||||
describe "success", ->
|
||||
@@ -115,6 +118,7 @@ describe "LineItems service", ->
|
||||
lineItem = new LineItemResource({ id: 15, order: { number: '12345678'} })
|
||||
LineItems.pristineByID[15] = lineItem
|
||||
LineItems.byID[15] = lineItem
|
||||
LineItems.all = [lineItem]
|
||||
$httpBackend.expectDELETE('/admin/bulk_line_items/15.json').respond 200, { id: 15, name: 'LineItem 1'}
|
||||
LineItems.delete(lineItem, callback).then( -> resolved = true).catch( -> rejected = true)
|
||||
$httpBackend.flush()
|
||||
@@ -122,6 +126,7 @@ describe "LineItems service", ->
|
||||
it "updates the pristine copy of the lineItem", ->
|
||||
expect(LineItems.pristineByID[15]).toBeUndefined()
|
||||
expect(LineItems.byID[15]).toBeUndefined()
|
||||
expect(LineItems.all).toEqual([])
|
||||
|
||||
it "runs the callback", ->
|
||||
expect(callback).toHaveBeenCalled()
|
||||
|
||||
Reference in New Issue
Block a user