Variant Overrides Index: User can manually reset inheritance

This commit is contained in:
Rob Harrington
2015-12-22 11:54:09 +11:00
parent 607a66b6c6
commit 0bbae19b41
13 changed files with 107 additions and 59 deletions

View File

@@ -9,13 +9,14 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
$scope.StatusMessage = StatusMessage
$scope.columns = Columns.setColumns
producer: { name: "Producer", visible: true }
product: { name: "Product", visible: true }
sku: { name: "SKU", visible: false }
price: { name: "Price", visible: true }
on_hand: { name: "On Hand", visible: true }
on_demand: { name: "On Demand", visible: false }
reset: { name: "Reset Stock Level", visible: false }
producer: { name: "Producer", visible: true }
product: { name: "Product", visible: true }
sku: { name: "SKU", visible: false }
price: { name: "Price", visible: true }
on_hand: { name: "On Hand", visible: true }
on_demand: { name: "On Demand", visible: false }
reset: { name: "Reset Stock Level", visible: false }
inheritance: { name: "Inheritance", visible: false }
$scope.resetSelectFilters = ->
$scope.producerFilter = 0

View File

@@ -0,0 +1,12 @@
angular.module("admin.variantOverrides").directive "trackInheritance", (VariantOverrides, DirtyVariantOverrides) ->
require: "ngModel"
link: (scope, element, attrs, ngModel) ->
# This is a bit hacky, but it allows us to load the inherit property on the VO, but then not submit it
scope.inherit = angular.equals scope.variantOverrides[scope.hub.id][scope.variant.id], VariantOverrides.newFor scope.hub.id, scope.variant.id
ngModel.$parsers.push (viewValue) ->
if ngModel.$dirty && viewValue
variantOverride = VariantOverrides.inherit(scope.hub.id, scope.variant.id)
DirtyVariantOverrides.add variantOverride
scope.displayDirty()
viewValue

View File

@@ -4,6 +4,7 @@ angular.module("admin.variantOverrides").directive "ofnTrackVariantOverride", (D
ngModel.$parsers.push (viewValue) ->
if ngModel.$dirty
variantOverride = scope.variantOverrides[scope.hub.id][scope.variant.id]
scope.inherit = false
DirtyVariantOverrides.add variantOverride
scope.displayDirty()
viewValue

View File

@@ -12,15 +12,24 @@ angular.module("admin.variantOverrides").factory "VariantOverrides", (variantOve
@variantOverrides[hub.id] ||= {}
for product in products
for variant in product.variants
@variantOverrides[hub.id][variant.id] ||=
variant_id: variant.id
hub_id: hub.id
sku: null
price: null
count_on_hand: null
on_demand: null
default_stock: null
resettable: false
@inherit(hub.id, variant.id) unless @variantOverrides[hub.id][variant.id]
inherit: (hub_id, variant_id) ->
# This method is called from the trackInheritance directive, to reinstate inheritance
@variantOverrides[hub_id][variant_id] ||= {}
angular.extend @variantOverrides[hub_id][variant_id], @newFor hub_id, variant_id
newFor: (hub_id, variant_id) ->
# These properties need to match those checked in VariantOverrideSet.deletable?
hub_id: hub_id
variant_id: variant_id
sku: null
price: null
count_on_hand: null
on_demand: null
default_stock: null
resettable: false
updateIds: (updatedVos) ->
for vo in updatedVos

View File

@@ -54,6 +54,7 @@ module Admin
@hub_permissions = OpenFoodNetwork::Permissions.new(spree_current_user).
variant_override_enterprises_per_hub
@variant_overrides = VariantOverride.for_hubs(@hubs)
end

View File

@@ -16,8 +16,8 @@ class ModelSet
end
end
def collection_attributes=(attributes)
attributes.each do |k, attributes|
def collection_attributes=(collection_attributes)
collection_attributes.each do |k, attributes|
# attributes == {:id => 123, :next_collection_at => '...'}
e = @collection.detect { |e| e.id.to_s == attributes[:id].to_s && !e.id.nil? }
if e.nil?
@@ -41,7 +41,11 @@ class ModelSet
end
def collection_to_delete
collection.select { |e| @delete_if.andand.call(e.attributes) }
# Remove all elements to be deleted from collection and return them
# Allows us to render @model_set.collection without deleted elements
deleted = []
collection.delete_if { |e| deleted << e if @delete_if.andand.call(e.attributes) }
deleted
end
def collection_to_keep
@@ -51,5 +55,4 @@ class ModelSet
def persisted?
false
end
end

View File

@@ -3,6 +3,8 @@ class VariantOverrideSet < ModelSet
super(VariantOverride, collection, attributes, nil, proc { |attrs| deletable?(attrs) } )
end
private
def deletable?(attrs)
attrs['price'].blank? &&
attrs['count_on_hand'].blank? &&

View File

@@ -1,4 +1,13 @@
%table.index.bulk{ ng: {show: 'hub'}}
%col.producer{ width: "20%", ng: { show: 'columns.producer.visible' } }
%col.product{ width: "20%", ng: { show: 'columns.product.visible' } }
%col.sku{ width: "20%", ng: { show: 'columns.sku.visible' } }
%col.price{ width: "10%", ng: { show: 'columns.price.visible' } }
%col.on_hand{ width: "10%", ng: { show: 'columns.on_hand.visible' } }
%col.on_demand{ width: "10%", ng: { show: 'columns.on_demand.visible' } }
%col.reset{ width: "1%", ng: { show: 'columns.reset.visible' } }
%col.reset{ width: "15%", ng: { show: 'columns.reset.visible' } }
%col.inheritance{ width: "5%", ng: { show: 'columns.inheritance.visible' } }
%thead
%tr{ ng: { controller: "ColumnsCtrl" } }
%th.producer{ ng: { show: 'columns.producer.visible' } } Producer
@@ -8,6 +17,7 @@
%th.on_hand{ ng: { show: 'columns.on_hand.visible' } } On hand
%th.on_demand{ ng: { show: 'columns.on_demand.visible' } } On Demand?
%th.reset{ colspan: 2, ng: { show: 'columns.reset.visible' } } Enable Stock Level Reset?
%th.inheritance{ ng: { show: 'columns.inheritance.visible' } } Inherit?
%tbody{bindonce: true, ng: {repeat: 'product in products | hubPermissions:hubPermissions:hub.id | attrFilter:{producer_id:producerFilter} | filter:query' } }
= render 'admin/variant_overrides/products_product'
= render 'admin/variant_overrides/products_variants'

View File

@@ -5,4 +5,5 @@
%td.price{ ng: { show: 'columns.price.visible' } }
%td.on_hand{ ng: { show: 'columns.on_hand.visible' } }
%td.on_demand{ ng: { show: 'columns.on_demand.visible' } }
%td{colspan: 2}
%td.reset{ colspan: 2, ng: { show: 'columns.reset.visible' } }
%td.inheritance{ ng: { show: 'columns.inheritance.visible' } }

View File

@@ -8,13 +8,12 @@
%td.price{ ng: { show: 'columns.price.visible' } }
%input{name: 'variant-overrides-{{ variant.id }}-price', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].price'}, placeholder: '{{ variant.price }}', 'ofn-track-variant-override' => 'price'}
%td.on_hand{ ng: { show: 'columns.on_hand.visible' } }
%input{name: 'variant-overrides-{{ variant.id }}-count_on_hand', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].count_on_hand'}, placeholder: '{{ variant.on_hand }}', 'ofn-track-variant-override' => 'price'}
%input{name: 'variant-overrides-{{ variant.id }}-count_on_hand', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].count_on_hand'}, placeholder: '{{ variant.on_hand }}', 'ofn-track-variant-override' => 'count_on_hand'}
%td.on_demand{ ng: { show: 'columns.on_demand.visible' } }
%input.field{ :type => 'checkbox', name: 'variant-overrides-{{ variant.id }}-on_demand', ng: { model: 'variantOverrides[hub.id][variant.id].on_demand' }, 'ofn-track-variant-override' => 'on_demand' }
%td
%input{name: 'variant-overrides-{{ variant.id }}-count-on-hand', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].count_on_hand'}, placeholder: '{{ variant.on_hand }}', 'ofn-track-variant-override' => 'count_on_hand'}
%td
%td.reset{ ng: { show: 'columns.reset.visible' } }
%input{name: 'variant-overrides-{{ variant.id }}-resettable', type: 'checkbox', ng: {model: 'variantOverrides[hub.id][variant.id].resettable'}, placeholder: '{{ variant.resettable }}', 'ofn-track-variant-override' => 'resettable'}
%td
%input{name: 'variant-overrides-{{ variant.id }}-default-stock', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].default_stock'}, placeholder: '{{ variant.default_stock ? variant.default_stock : "Default stock"}}', 'ofn-track-variant-override' => 'default_stock'}
%td.reset{ ng: { show: 'columns.reset.visible' } }
%input{name: 'variant-overrides-{{ variant.id }}-default_stock', type: 'text', ng: {model: 'variantOverrides[hub.id][variant.id].default_stock'}, placeholder: '{{ variant.default_stock ? variant.default_stock : "Default stock"}}', 'ofn-track-variant-override' => 'default_stock'}
%td.inheritance{ ng: { show: 'columns.inheritance.visible' } }
%input.field{ :type => 'checkbox', name: 'variant-overrides-{{ variant.id }}-inherit', ng: { model: 'inherit' }, 'track-inheritance' => true }

View File

@@ -55,11 +55,11 @@ feature %q{
it "displays the list of products with variants" do
page.should have_table_row ['PRODUCER', 'PRODUCT', 'PRICE', 'ON HAND']
page.should have_table_row [producer.name, product.name, '', '', '']
page.should have_table_row [producer.name, product.name, '', '']
page.should have_input "variant-overrides-#{variant.id}-price", placeholder: '1.23'
page.should have_input "variant-overrides-#{variant.id}-count_on_hand", placeholder: '12'
page.should have_table_row [producer_related.name, product_related.name, '', '', '']
page.should have_table_row [producer_related.name, product_related.name, '', '']
page.should have_input "variant-overrides-#{variant_related.id}-price", placeholder: '2.34'
page.should have_input "variant-overrides-#{variant_related.id}-count_on_hand", placeholder: '23'
@@ -186,6 +186,9 @@ feature %q{
let!(:product2) { create(:simple_product, supplier: producer, variant_unit: 'weight', variant_unit_scale: 1) }
let!(:variant2) { create(:variant, product: product2, unit_value: 8, price: 1.00, on_hand: 12) }
let!(:vo_no_reset) { create(:variant_override, variant: variant2, hub: hub, price: 3.99, count_on_hand: 40, default_stock: 100, resettable: false) }
let!(:variant3) { create(:variant, product: product, unit_value: 2, price: 5.00, on_hand: 6) }
let!(:vo3) { create(:variant_override, variant: variant3, hub: hub, price: 6, count_on_hand: 7, sku: "SOMESKU", default_stock: 100, resettable: false) }
before do
visit '/admin/variant_overrides'
select2_select hub.name, from: 'hub_id'
@@ -216,23 +219,30 @@ feature %q{
# Any new fields added to the VO model need to be added to this test
it "deletes overrides when values are cleared" do
first("div#columns-dropdown", :text => "COLUMNS").click
first("div#columns-dropdown div.menu div.menu_item", text: "SKU").click
first("div#columns-dropdown div.menu div.menu_item", text: "On Demand").click
first("div#columns-dropdown div.menu div.menu_item", text: "Reset Stock Level").click
first("div#columns-dropdown", :text => "COLUMNS").click
# Clearing values manually
fill_in "variant-overrides-#{variant.id}-price", with: ''
fill_in "variant-overrides-#{variant.id}-count-on-hand", with: ''
fill_in "variant-overrides-#{variant.id}-default-stock", with: ''
page.uncheck "variant-overrides-#{variant.id}-resettable"
page.should have_content "Changes to one override remain unsaved."
# Clearing values by 'inheriting'
first("div#columns-dropdown", :text => "COLUMNS").click
first("div#columns-dropdown div.menu div.menu_item", text: "Inheritance").click
first("div#columns-dropdown", :text => "COLUMNS").click
page.check "variant-overrides-#{variant3.id}-inherit"
expect do
click_button 'Save Changes'
page.should have_content "Changes saved."
end.to change(VariantOverride, :count).by(-1)
end.to change(VariantOverride, :count).by(-2)
VariantOverride.where(id: vo.id).should be_empty
VariantOverride.where(id: vo3.id).should be_empty
end
it "resets stock to defaults" do

View File

@@ -21,11 +21,11 @@ describe "VariantOverridesCtrl", ->
null
scope = {}
inject ($controller, Indexer, _VariantOverrides_, _DirtyVariantOverrides_, _StatusMessage_) ->
inject ($controller, _VariantOverrides_, _DirtyVariantOverrides_, _StatusMessage_) ->
VariantOverrides = _VariantOverrides_
DirtyVariantOverrides = _DirtyVariantOverrides_
StatusMessage = _StatusMessage_
ctrl = $controller 'AdminVariantOverridesCtrl', {$scope: scope, hubs: hubs, producers: producers, products: products, hubPermissions: hubPermissions, VariantOverrides: _VariantOverrides_, DirtyVariantOverrides: _DirtyVariantOverrides_, StatusMessage: _StatusMessage_}
ctrl = $controller 'AdminVariantOverridesCtrl', { $scope: scope, hubs: hubs, producers: producers, products: products, hubPermissions: hubPermissions, VariantOverrides: VariantOverrides, DirtyVariantOverrides: DirtyVariantOverrides, StatusMessage: StatusMessage}
it "initialises the hub list and the chosen hub", ->
expect(scope.hubs).toEqual { 1: {id: 1, name: 'Hub'} }

View File

@@ -1,9 +1,9 @@
describe "VariantOverrides service", ->
VariantOverrides = $httpBackend = null
variantOverrides = [
{id: 1, hub_id: 10, variant_id: 100, price: 1, count_on_hand: 1, default_stock: '', resettable: false}
{id: 2, hub_id: 10, variant_id: 200, price: 2, count_on_hand: 2, default_stock: '', resettable: false}
{id: 3, hub_id: 20, variant_id: 300, price: 3, count_on_hand: 3, default_stock: '', resettable: false}
{id: 1, hub_id: 10, variant_id: 100, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false }
{id: 2, hub_id: 10, variant_id: 200, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false}
{id: 3, hub_id: 20, variant_id: 300, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false}
]
beforeEach ->
@@ -19,10 +19,10 @@ describe "VariantOverrides service", ->
it "indexes variant overrides by hub_id -> variant_id", ->
expect(VariantOverrides.variantOverrides).toEqual
10:
100: {id: 1, hub_id: 10, variant_id: 100, price: 1, count_on_hand: 1, default_stock: '', resettable: false}
200: {id: 2, hub_id: 10, variant_id: 200, price: 2, count_on_hand: 2, default_stock: '', resettable: false}
100: {id: 1, hub_id: 10, variant_id: 100, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false }
200: {id: 2, hub_id: 10, variant_id: 200, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false }
20:
300: {id: 3, hub_id: 20, variant_id: 300, price: 3, count_on_hand: 3, default_stock: '', resettable: false}
300: {id: 3, hub_id: 20, variant_id: 300, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false }
it "ensures blank data available for some products", ->
hubs = [{id: 10}, {id: 20}, {id: 30}]
@@ -33,25 +33,24 @@ describe "VariantOverrides service", ->
}
]
VariantOverrides.ensureDataFor hubs, products
expect(VariantOverrides.variantOverrides).toEqual
10:
100: {id: 1, hub_id: 10, variant_id: 100, price: 1, count_on_hand: 1, default_stock: '', resettable: false}
200: {id: 2, hub_id: 10, variant_id: 200, price: 2, count_on_hand: 2, default_stock: '', resettable: false}
300: { hub_id: 10, variant_id: 300, price: '', count_on_hand: '', default_stock: '', resettable: false}
400: { hub_id: 10, variant_id: 400, price: '', count_on_hand: '', default_stock: '', resettable: false}
500: { hub_id: 10, variant_id: 500, price: '', count_on_hand: '', default_stock: '', resettable: false}
20:
100: { hub_id: 20, variant_id: 100, price: '', count_on_hand: '', default_stock: '', resettable: false}
200: { hub_id: 20, variant_id: 200, price: '', count_on_hand: '', default_stock: '', resettable: false}
300: {id: 3, hub_id: 20, variant_id: 300, price: 3, count_on_hand: 3, default_stock: '', resettable: false}
400: { hub_id: 20, variant_id: 400, price: '', count_on_hand: '', default_stock: '', resettable: false}
500: { hub_id: 20, variant_id: 500, price: '', count_on_hand: '', default_stock: '', resettable: false}
30:
100: { hub_id: 30, variant_id: 100, price: '', count_on_hand: '', default_stock: '', resettable: false}
200: { hub_id: 30, variant_id: 200, price: '', count_on_hand: '', default_stock: '', resettable: false}
300: { hub_id: 30, variant_id: 300, price: '', count_on_hand: '', default_stock: '', resettable: false}
400: { hub_id: 30, variant_id: 400, price: '', count_on_hand: '', default_stock: '', resettable: false}
500: { hub_id: 30, variant_id: 500, price: '', count_on_hand: '', default_stock: '', resettable: false}
expect(VariantOverrides.variantOverrides[10]).toEqual
100: { id: 1, hub_id: 10, variant_id: 100, sku: "V100", price: 1, count_on_hand: 1, on_demand: null, default_stock: null, resettable: false }
200: { id: 2, hub_id: 10, variant_id: 200, sku: "V200", price: 2, count_on_hand: 2, on_demand: null, default_stock: null, resettable: false }
300: { hub_id: 10, variant_id: 300, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
400: { hub_id: 10, variant_id: 400, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
500: { hub_id: 10, variant_id: 500, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
expect(VariantOverrides.variantOverrides[20]).toEqual
100: { hub_id: 20, variant_id: 100, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
200: { hub_id: 20, variant_id: 200, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
300: { id: 3, hub_id: 20, variant_id: 300, sku: "V300", price: 3, count_on_hand: 3, on_demand: null, default_stock: null, resettable: false }
400: { hub_id: 20, variant_id: 400, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
500: { hub_id: 20, variant_id: 500, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
expect(VariantOverrides.variantOverrides[30]).toEqual
100: { hub_id: 30, variant_id: 100, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
200: { hub_id: 30, variant_id: 200, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
300: { hub_id: 30, variant_id: 300, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
400: { hub_id: 30, variant_id: 400, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
500: { hub_id: 30, variant_id: 500, sku: null, price: null, count_on_hand: null, on_demand: null, default_stock: null, resettable: false }
it "updates the IDs of variant overrides", ->
VariantOverrides.variantOverrides[2] = {}