BPUR: can update master on_hand

This commit is contained in:
Rob H
2013-05-17 19:27:12 +05:30
committed by Rohan Mitchell
parent fbb3657bdc
commit f3d778af1a
6 changed files with 164 additions and 24 deletions

View File

@@ -36,22 +36,25 @@ productsApp.directive('ngDecimal', function () {
}
});
productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http) {
productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http, dataFetcher) {
$scope.refreshSuppliers = function(){
$http.get('/enterprises/suppliers.json').success(function(data) {
dataFetcher('/enterprises/suppliers.json').then(function(data){
$scope.suppliers = data;
});
};
$scope.refreshProducts = function(){
$http({ method: 'GET', url:'/admin/products/bulk_index.json' }).success(function(data) {
dataFetcher('/admin/products/bulk_index.json').then(function(data){
$scope.products = angular.copy(data);
$scope.cleanProducts = angular.copy(data);
});
}
};
$scope.refreshSuppliers();
$scope.refreshProducts();
//accessible from scope
$scope.onHand = function(products){
return onHand(products);
}
$scope.updateStatusMessage = {
text: "",
style: {}
@@ -66,6 +69,7 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http
})
.success(function(data){
if (angular.toJson($scope.products) == angular.toJson(data)){
$scope.cleanProducts = angular.copy(data);
$scope.displaySuccess();
}
else{
@@ -104,6 +108,31 @@ productsApp.controller('AdminBulkProductsCtrl', function($scope, $timeout, $http
}
});
productsApp.factory('dataFetcher', function($http,$q){
return function(dataLocation){
var deferred = $q.defer();
$http.get(dataLocation).success(function(data) {
deferred.resolve(data);
}).error(function(){
deferred.reject();
});
return deferred.promise;
};
});
function onHand(product){
var onHand = 0;
if(product.hasOwnProperty('variants') && product.variants instanceof Array){
angular.forEach(product.variants, function(variant) {
onHand = parseInt( onHand ) + parseInt( variant.on_hand > 0 ? variant.on_hand : 0 );
});
}
else{
onHand = 'error';
}
return onHand;
}
function sortByID(array){
var sortedArray = [];
for (var i in array){

View File

@@ -11,13 +11,14 @@
%div#new_product(data-hook)
%div{ 'ng-app' => 'bulk_product_update', 'ng-controller' => 'AdminBulkProductsCtrl' }
%div{ 'ng-app' => 'bulk_product_update', 'ng-controller' => 'AdminBulkProductsCtrl', 'ng-init' => 'refreshSuppliers(); refreshProducts()' }
%table.index#listing_products
%thead
%tr
%th Name
%th Supplier
%th Price
%th On Hand
%th Av. On
%tbody{ 'ng-repeat' => 'product in products | filter:query' }
%tr
@@ -27,6 +28,9 @@
%select.select2{ :name => 'supplier_id', 'ng-model' => 'product.supplier_id', 'ng-options' => 's.id as s.name for s in suppliers' }
%td
%input{ 'ng-model' => 'product.master.price', 'ng-decimal' => :true, :name => 'master_price', :type => 'text' }
%td
%span{ 'ng-bind' => 'onHand(product)', :name => 'master_on_hand', 'ng-show' => 'product.variants.length > 0' }
%input.field{ 'ng-model' => 'product.master.on_hand', :name => 'master_on_hand', 'ng-show' => 'product.variants.length == 0', :type => 'number' }
%td
%input{ 'ng-model' => 'product.available_on', :name => 'available_on', :type => 'text' }
%input{:type => 'button', :value => 'Update', 'ng-click' => 'prepareProductsForSubmit()'}

View File

@@ -6,5 +6,10 @@ r.list_of :products, @collection do
r.element :master do
r.element :id
r.element :price
r.element :on_hand
end
r.list_of :variants, Proc.new{ |product| product.variants.sort { |a,b| a.id <=> b.id } } do
r.element :id
r.element :on_hand
end
end

View File

@@ -22,6 +22,10 @@ describe Spree::Admin::ProductsController do
it "collects returns products in an array formatted as json" do
p1 = FactoryGirl.create(:product)
p2 = FactoryGirl.create(:product)
v11 = FactoryGirl.create(:variant, product: p1, on_hand: 1)
v12 = FactoryGirl.create(:variant, product: p1, on_hand: 2)
v13 = FactoryGirl.create(:variant, product: p1, on_hand: 3)
v21 = FactoryGirl.create(:variant, product: p2, on_hand: 4)
spree_get :bulk_index, { format: :json }
p1r = {
@@ -31,8 +35,14 @@ describe Spree::Admin::ProductsController do
"available_on" => p1.available_on.strftime("%F %T"),
"master" => {
"id" => p1.master.id,
"price" => p1.master.price.to_s
}
"price" => p1.master.price.to_s,
"on_hand" => p1.master.on_hand
},
"variants" => [ #ordered by id
{ "id" => v11.id, "on_hand" => v11.on_hand },
{ "id" => v12.id, "on_hand" => v12.on_hand },
{ "id" => v13.id, "on_hand" => v13.on_hand }
]
}
p2r = {
"id" => p2.id,
@@ -41,8 +51,12 @@ describe Spree::Admin::ProductsController do
"available_on" => p2.available_on.strftime("%F %T"),
"master" => {
"id" => p2.master.id,
"price" => p2.master.price.to_s
}
"price" => p2.master.price.to_s,
"on_hand" => p2.master.on_hand
},
"variants" => [ #ordered by id
{ "id" => v21.id, "on_hand" => v21.on_hand }
]
}
json_response = JSON.parse(response.body)
#json_response = Hash[json_response.map{ |k, v| [k.to_sym, v] }]

View File

@@ -67,6 +67,37 @@ feature %q{
page.should have_field "master_price", with: "22.0"
page.should have_field "master_price", with: "44.0"
end
it "displays an on hand count input (for master variant) for each product if no other variants exist" do
p1 = FactoryGirl.create(:product)
p2 = FactoryGirl.create(:product)
p1.master.on_hand = 15
p2.master.on_hand = 12
p1.save!
p2.save!
visit '/admin/products/bulk_index'
page.should_not have_selector "span[name='master_on_hand']", text: "0"
page.should have_field "master_on_hand", with: "15"
page.should have_field "master_on_hand", with: "12"
end
it "displays an on hand count in a span (for master variant) for each product if other variants exist" do
p1 = FactoryGirl.create(:product)
p2 = FactoryGirl.create(:product)
v1 = FactoryGirl.create(:variant, product: p1, is_master: false, on_hand: 4)
p1.master.on_hand = 15
p2.master.on_hand = 12
p1.save!
p2.save!
visit '/admin/products/bulk_index'
page.should_not have_field "master_on_hand", with: "15"
page.should have_selector "span[name='master_on_hand']", text: "4"
page.should have_field "master_on_hand", with: "12"
end
end
scenario "create a new product" do
@@ -94,11 +125,12 @@ feature %q{
page.should have_field "product_name", with: 'Big Bag Of Apples'
end
scenario "updating a product" do
scenario "updating a product with no variants (except master)" do
s1 = FactoryGirl.create(:supplier_enterprise)
s2 = FactoryGirl.create(:supplier_enterprise)
p = FactoryGirl.create(:product, supplier: s1, available_on: Date.today)
p.master.price = 10.0
p.master.on_hand = 6;
p.save!
login_to_admin_section
@@ -109,11 +141,13 @@ feature %q{
page.should have_select "supplier_id", selected: s1.name
page.should have_field "available_on", with: p.available_on.strftime("%F %T")
page.should have_field "master_price", with: "10.0"
page.should have_field "master_on_hand", with: "6"
fill_in "product_name", with: "Big Bag Of Potatoes"
select(s2.name, :from => 'supplier_id')
fill_in "available_on", with: (Date.today-3).strftime("%F %T")
fill_in "master_price", with: "20"
fill_in "master_on_hand", with: "18"
click_button 'Update'
page.find("span#update-status-message").should have_content "Update complete"
@@ -124,5 +158,30 @@ feature %q{
page.should have_select "supplier_id", selected: s2.name
page.should have_field "available_on", with: (Date.today-3).strftime("%F %T")
page.should have_field "master_price", with: "20.0"
page.should have_field "master_on_hand", with: "18"
end
scenario "updating a product mutiple times without refresh" do
p = FactoryGirl.create(:product, name: 'original name')
login_to_admin_section
visit '/admin/products/bulk_index'
page.should have_field "product_name", with: "original name"
fill_in "product_name", with: "new name 1"
click_button 'Update'
page.find("span#update-status-message").should have_content "Update complete"
fill_in "product_name", with: "new name 2"
click_button 'Update'
page.find("span#update-status-message").should have_content "Update complete"
fill_in "product_name", with: "original name"
click_button 'Update'
page.find("span#update-status-message").should have_content "Update complete"
end
end

View File

@@ -281,22 +281,28 @@ describe("AdminBulkProductsCtrl", function(){
scope = $rootScope.$new();
ctrl = $controller;
httpBackend = $httpBackend;
ctrl('AdminBulkProductsCtrl', { $scope: scope } );
}));
it("gets a list of suppliers, a list of products and stores a clean list of products", function(){
it("gets a list of suppliers", function(){
httpBackend.expectGET('/enterprises/suppliers.json').respond("list of suppliers");
httpBackend.expectGET('/admin/products/bulk_index.json').respond("list of products");
ctrl('AdminBulkProductsCtrl', { $scope: scope } );
scope.refreshSuppliers();
httpBackend.flush();
expect(scope.suppliers).toEqual("list of suppliers");
});
it("gets a list of products and stores a clean list of products", function(){
httpBackend.expectGET('/admin/products/bulk_index.json').respond("list of products");
scope.refreshProducts();
httpBackend.flush();
expect(scope.products).toEqual("list of products");
expect(scope.cleanProducts).toEqual("list of products");
});
it("does not affect clean products list when products list is altered", function(){
httpBackend.expectGET('/enterprises/suppliers.json').respond("list of suppliers");
httpBackend.expectGET('/admin/products/bulk_index.json').respond( [1,2,3,4,5] );
ctrl('AdminBulkProductsCtrl', { $scope: scope } );
scope.refreshProducts();
httpBackend.flush();
expect(scope.products).toEqual( [1,2,3,4,5] );
expect(scope.cleanProducts).toEqual( [1,2,3,4,5] );
@@ -305,6 +311,33 @@ describe("AdminBulkProductsCtrl", function(){
expect(scope.cleanProducts).toEqual( [1,2,3,4,5] );
});
});
describe("getting on_hand counts when products have variants", function(){
var p1, p2, p3;
beforeEach(function(){
p1 = { variants: [ { on_hand: 1 }, { on_hand: 2 }, { on_hand: 3 } ] };
p2 = { variants: [ { not_on_hand: 1 }, { on_hand: 2 }, { on_hand: 3 } ] };
p3 = { not_variants: [ { on_hand: 1 }, { on_hand: 2 } ], variants: [ { on_hand: 3 } ] };
});
it("sums variant on_hand properties", function(){
expect(onHand(p1)).toEqual(6);r
});
it("ignores items in variants without an on_hand property (adds 0)", function(){
expect(onHand(p2)).toEqual(5);
});
it("ignores on_hand properties of objects in arrays which are not named 'variants' (adds 0)", function(){
expect(onHand(p3)).toEqual(3);
});
it("returns 'error' if not given an object with a variants property that is an array", function(){
expect( onHand([]) ).toEqual('error');
expect( onHand( { not_variants: [] } ) ).toEqual('error');
expect( onHand( { variants: {} } ) ).toEqual('error');
});
});
describe("submitting products to be updated", function(){
ctrl = null;
@@ -325,13 +358,12 @@ describe("AdminBulkProductsCtrl", function(){
describe("preparing products for submit",function(){
beforeEach(function(){
httpBackend.expectGET('/enterprises/suppliers.json').respond("list of suppliers");
httpBackend.expectGET('/admin/products/bulk_index.json').respond( [1,2,3,4,5] );
ctrl('AdminBulkProductsCtrl', { $scope: scope } );
httpBackend.flush();
spyOn(window, "getDirtyObjects").andReturn( [ { id: 1, value: 1 }, { id:2, value: 2 } ] );
spyOn(window, "filterSubmitProducts").andReturn( [ { id: 1, value: 3 }, { id:2, value: 4 } ] );
spyOn(scope, "updateProducts");
scope.products = [1,2,3,4,5];
scope.cleanProducts = [1,2,3,4,5];
scope.prepareProductsForSubmit();
});
@@ -350,10 +382,7 @@ describe("AdminBulkProductsCtrl", function(){
describe("updating products",function(){
beforeEach(function(){
httpBackend.expectGET('/enterprises/suppliers.json').respond("list of suppliers");
httpBackend.expectGET('/admin/products/bulk_index.json').respond("list of products");
ctrl('AdminBulkProductsCtrl', { $scope: scope, $timeout: timeout } );
httpBackend.flush();
});
it("submits products to be updated with a http post request to /admin/products/bulk_update", function(){
@@ -387,7 +416,7 @@ describe("AdminBulkProductsCtrl", function(){
scope.updateProducts("updated list of products");
httpBackend.flush();
expect(scope.displayFailure).toHaveBeenCalled();
});
});
});
});