Merge branch 'master' into redesign

This commit is contained in:
Rohan Mitchell
2015-05-29 17:37:18 +10:00
20 changed files with 96 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $http, BulkProducts, DisplayProperties, dataFetcher, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth) ->
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $http, BulkProducts, DisplayProperties, dataFetcher, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth, tax_categories) ->
$scope.loading = true
$scope.StatusMessage = StatusMessage
@@ -10,7 +10,9 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
unit: {name: "Unit", visible: true}
price: {name: "Price", visible: true}
on_hand: {name: "On Hand", visible: true}
on_demand: {name: "On Demand", visible: false}
category: {name: "Category", visible: false}
tax_category: {name: "Tax Category", visible: false}
inherits_properties: {name: "Inherits Properties?", visible: false}
available_on: {name: "Available On", visible: false}
@@ -32,6 +34,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.producers = producers
$scope.taxons = Taxons.taxons
$scope.tax_categories = tax_categories
$scope.filterProducers = [{id: "0", name: ""}].concat $scope.producers
$scope.filterTaxons = [{id: "0", name: ""}].concat $scope.taxons
$scope.producerFilter = "0"
@@ -312,9 +315,15 @@ filterSubmitProducts = (productsToFilter) ->
if product.hasOwnProperty("on_hand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_hand = product.on_hand
hasUpdatableProperty = true
if product.hasOwnProperty("on_demand") and filteredVariants.length == 0 #only update if no variants present
filteredProduct.on_demand = product.on_demand
hasUpdatableProperty = true
if product.hasOwnProperty("category_id")
filteredProduct.primary_taxon_id = product.category_id
hasUpdatableProperty = true
if product.hasOwnProperty("tax_category_id")
filteredProduct.tax_category_id = product.tax_category_id
hasUpdatableProperty = true
if product.hasOwnProperty("inherits_properties")
filteredProduct.inherits_properties = product.inherits_properties
hasUpdatableProperty = true
@@ -340,6 +349,9 @@ filterSubmitVariant = (variant) ->
if variant.hasOwnProperty("on_hand")
filteredVariant.on_hand = variant.on_hand
hasUpdatableProperty = true
if variant.hasOwnProperty("on_demand")
filteredVariant.on_demand = variant.on_demand
hasUpdatableProperty = true
if variant.hasOwnProperty("price")
filteredVariant.price = variant.price
hasUpdatableProperty = true

View File

@@ -19,7 +19,7 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher)
# when a respond_overrride for the clone action is used.
id = data.product.id
dataFetcher("/api/products/" + id + "?template=bulk_show").then (newProduct) =>
@addProducts [newProduct]
@insertProductAfter(product, newProduct)
updateVariantLists: (serverProducts, productsWithUnsavedVariants) ->
for product in productsWithUnsavedVariants
@@ -39,6 +39,10 @@ angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher)
@unpackProduct product
@products.push product
insertProductAfter: (product, newProduct) ->
index = @products.indexOf(product)
@products.splice(index + 1, 0, newProduct)
unpackProduct: (product) ->
#$scope.matchProducer product
@loadVariantUnit product

View File

@@ -23,6 +23,13 @@ Spree::Admin::OrdersController.class_eval do
distributed_by_user(spree_current_user).
page(params[:page]).
per(params[:per_page] || Spree::Config[:orders_per_page])
# Filter orders by distributor
if params[:distributor_ids]
@orders = @orders.where(distributor_id: params[:distributor_ids])
end
if params[:order_cycle_ids]
@orders = @orders.where(order_cycle_id: params[:order_cycle_ids])
end
} } }
# Overwrite to use confirm_email_for_customer instead of confirm_email.

View File

@@ -50,6 +50,10 @@ module Admin
admin_inject_json_ams_array "ofn.admin", "products", @products, Api::Admin::ProductSerializer
end
def admin_inject_tax_categories
admin_inject_json_ams_array "ofn.admin", "tax_categories", @tax_categories, Api::Admin::TaxCategorySerializer
end
def admin_inject_taxons
admin_inject_json_ams_array "admin.taxons", "taxons", @taxons, Api::Admin::TaxonSerializer
end

View File

@@ -109,6 +109,12 @@ Spree::Product.class_eval do
# -- Methods
# Called by Spree::Product::duplicate before saving.
def duplicate_extra(parent)
# Spree sets the SKU to "COPY OF #{parent sku}".
self.master.sku = ''
end
def properties_including_inherited
# Product properties override producer properties
ps = product_properties.all

View File

@@ -7,6 +7,7 @@ Spree::Variant.class_eval do
has_many :exchange_variants, dependent: :destroy
has_many :exchanges, through: :exchange_variants
has_many :variant_overrides
attr_accessible :unit_value, :unit_description, :images_attributes, :display_as, :display_name
accepts_nested_attributes_for :images

View File

@@ -0,0 +1,13 @@
/ insert_before "div.clearfix"
.field-block.alpha.eight.columns
= label_tag nil, t(:distributors)
= select_tag(:distributor_ids,
options_for_select(Enterprise.is_distributor.managed_by(spree_current_user).map {|e| [e.name, e.id]}, params[:distributor_ids]),
{class: "select2 fullwidth", multiple: true})
.field-block.alpha.eight.columns
= label_tag nil, t(:order_cycles)
= select_tag(:order_cycle_ids,
options_for_select(OrderCycle.managed_by(spree_current_user).map {|oc| [oc.name, oc.id]}, params[:order_cycle_ids]),
{class: "select2 fullwidth", multiple: true})

View File

@@ -38,20 +38,26 @@
.twelve.columns.alpha
.six.columns.alpha
= render 'spree/admin/products/primary_taxon_form', f: f
.three.columns
.two.columns
= f.field_container :price do
= f.label :price, t(:price)
%span.required *
%br/
= f.text_field :price, class: 'fullwidth'
= f.error_message_on :price
.three.columns.omega
.two.columns
= f.field_container :on_hand do
= f.label :on_hand, t(:on_hand)
%span.required *
%br/
= f.text_field :on_hand, class: 'fullwidth'
= f.error_message_on :on_hand
.two.columns.omega
= f.field_container :on_demand do
= f.label :on_demand, t(:on_demand)
%br/
= f.check_box :on_demand
= f.error_message_on :on_demand
.twelve.columns.alpha
.six.columns.alpha  
.three.columns

View File

@@ -1,7 +1,7 @@
class Api::Admin::ProductSerializer < ActiveModel::Serializer
attributes :id, :name, :sku, :variant_unit, :variant_unit_scale, :variant_unit_name, :on_demand, :inherits_properties
attributes :on_hand, :price, :available_on, :permalink_live
attributes :on_hand, :price, :available_on, :permalink_live, :tax_category_id
has_one :supplier, key: :producer_id, embed: :id
has_one :primary_taxon, key: :category_id, embed: :id

View File

@@ -0,0 +1,3 @@
class Api::Admin::TaxCategorySerializer < ActiveModel::Serializer
attributes :id, :name
end

View File

@@ -1,6 +1,7 @@
class Api::Admin::VariantSerializer < ActiveModel::Serializer
attributes :id, :options_text, :unit_value, :unit_description, :unit_to_display, :on_demand, :display_as, :display_name, :name_to_display
attributes :on_hand, :price
has_many :variant_overrides
def on_hand
object.on_hand.nil? ? 0 : ( object.on_hand.to_f.finite? ? object.on_hand : "On demand" )

View File

@@ -8,3 +8,4 @@
= render 'spree/admin/products/bulk_edit/actions'
= render 'spree/admin/products/bulk_edit/indicators'
= render 'spree/admin/products/bulk_edit/products'
= render 'spree/admin/products/bulk_edit/save_button_row'

View File

@@ -1,3 +1,4 @@
= admin_inject_producers
= admin_inject_taxons
= admin_inject_tax_categories
= admin_inject_spree_api_key

View File

@@ -7,7 +7,9 @@
%col.display_as{ ng: { show: 'columns.unit.visible' } }
%col.price{ ng: { show: 'columns.price.visible'} }
%col.on_hand{ ng: { show: 'columns.on_hand.visible' } }
%col.on_demand{ ng: { show: 'columns.on_demand.visible' } }
%col.category{ ng: { show: 'columns.category.visible' } }
%col.tax_category{ ng: { show: 'columns.tax_category.visible' } }
%col.inherits_properties{ ng: { show: 'columns.inherits_properties.visible' } }
%col.available_on{ ng: { show: 'columns.available_on.visible' } }
%col.actions
@@ -24,7 +26,9 @@
%th.display_as{ 'ng-show' => 'columns.unit.visible' } Display As
%th.price{ 'ng-show' => 'columns.price.visible' } Price
%th.on_hand{ 'ng-show' => 'columns.on_hand.visible' } On Hand
%th.on_demand{ 'ng-show' => 'columns.on_demand.visible' } On Demand
%th.category{ 'ng-show' => 'columns.category.visible' } Category
%th.tax_category{ 'ng-show' => 'columns.tax_category.visible' } Tax Category
%th.inherits_properties{ 'ng-show' => 'columns.inherits_properties.visible' } Inherits Properties?
%th.available_on{ 'ng-show' => 'columns.available_on.visible' } Av. On
%th.actions

View File

@@ -20,8 +20,13 @@
%td.on_hand{ 'ng-show' => 'columns.on_hand.visible' }
%span{ 'ng-bind' => 'product.on_hand', :name => 'on_hand', 'ng-show' => '!hasOnDemandVariants(product) && (hasVariants(product) || product.on_demand)' }
%input.field{ 'ng-model' => 'product.on_hand', :name => 'on_hand', 'ofn-track-product' => 'on_hand', 'ng-hide' => 'hasVariants(product) || product.on_demand', :type => 'number' }
%td.on_demand{ 'ng-show' => 'columns.on_demand.visible' }
%input.field{ 'ng-model' => 'product.on_demand', :name => 'on_demand', 'ofn-track-product' => 'on_demand', :type => 'checkbox', 'ng-hide' => 'hasVariants(product)' }
%td.category{ 'ng-if' => 'columns.category.visible' }
%input.fullwidth{ :type => 'text', id: "p{{product.id}}_category_id", 'ng-model' => 'product.category_id', 'ofn-taxon-autocomplete' => '', 'ofn-track-product' => 'category_id', 'multiple-selection' => 'false', placeholder: 'Category' }
%td.tax_category{ 'ng-if' => 'columns.tax_category.visible' }
%select.select2{ name: 'product_tax_category_id', 'ofn-track-product' => 'tax_category_id', ng: {model: 'product.tax_category_id', options: 'tax_category.id as tax_category.name for tax_category in tax_categories'} }
%option{value: ''} None
%td.inherits_properties{ 'ng-show' => 'columns.inherits_properties.visible' }
%input{ 'ng-model' => 'product.inherits_properties', :name => 'inherits_properties', 'ofn-track-product' => 'inherits_properties', type: "checkbox" }
%td.available_on{ 'ng-show' => 'columns.available_on.visible' }

View File

@@ -15,11 +15,15 @@
%td{ 'ng-show' => 'columns.on_hand.visible' }
%input.field{ 'ng-model' => 'variant.on_hand', 'ng-change' => 'updateOnHand(product)', :name => 'variant_on_hand', 'ng-hide' => 'variant.on_demand', 'ofn-track-variant' => 'on_hand', :type => 'number' }
%span{ 'ng-bind' => 'variant.on_hand', :name => 'variant_on_hand', 'ng-show' => 'variant.on_demand' }
%td{ 'ng-show' => 'columns.on_demand.visible' }
%input.field{ 'ng-model' => 'variant.on_demand', :name => 'variant_on_demand', 'ofn-track-variant' => 'on_demand', :type => 'checkbox' }
%td{ 'ng-show' => 'columns.category.visible' }
%td{ 'ng-show' => 'columns.tax_category.visible' }
%td{ 'ng-show' => 'columns.inherits_properties.visible' }
%td{ 'ng-show' => 'columns.available_on.visible' }
%td.actions
%a{ 'ng-click' => 'editWarn(product,variant)', :class => "edit-variant icon-edit no-text", 'ng-show' => "variantSaved(variant)" }
%td.actions
%span.icon-warning-sign.with-tip{ 'ng-if' => 'variant.variant_overrides', title: "This variant has {{variant.variant_overrides.length}} override(s)" }
%td.actions
%a{ 'ng-click' => 'deleteVariant(product,variant)', "ng-class" => '{disabled: product.variants.length < 2}', :class => "delete-variant icon-trash no-text" }

View File

@@ -0,0 +1,3 @@
%div.sixteen.columns.alpha{ 'ng-hide' => 'loading || products.length == 0', style: "margin-bottom: 10px" }
%div.four.columns.alpha
%input.four.columns.alpha{ :type => 'button', :value => 'Save Changes', 'ng-click' => 'submitProducts()'}

View File

@@ -216,7 +216,7 @@ feature %q{
fill_in "variant_price", with: "4.0"
fill_in "variant_on_hand", with: "10"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
updated_variant = Spree::Variant.where(deleted_at: nil).last
@@ -266,7 +266,7 @@ feature %q{
fill_in "product_sku", with: "NEW SKU"
end
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
@@ -292,7 +292,7 @@ feature %q{
select "Items", from: "variant_unit_with_scale"
fill_in "variant_unit_name", with: "loaf"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
@@ -326,7 +326,7 @@ feature %q{
expect(page).to have_selector "span[name='on_hand']", text: "10"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
v.reload
@@ -352,7 +352,7 @@ feature %q{
fill_in "variant_price", with: "10.0"
end
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
v.reload
@@ -369,21 +369,21 @@ feature %q{
fill_in "product_name", with: "new name 1"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "new name 1"
fill_in "product_name", with: "new name 2"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "new name 2"
fill_in "product_name", with: "original name"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "original name"
@@ -399,7 +399,7 @@ feature %q{
fill_in "product_name", :with => "new product name"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload
expect(p.name).to eq "new product name"
@@ -412,7 +412,7 @@ feature %q{
visit '/admin/products/bulk_edit'
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "No changes to save."
end
end
@@ -431,7 +431,7 @@ feature %q{
expect(page).to have_no_field "product_name", with: p2.name
fill_in "product_name", :with => "new product1"
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p1.reload
expect(p1.name).to eq "new product1"
@@ -709,7 +709,7 @@ feature %q{
fill_in "variant_display_as", with: "Big Bag"
end
click_button 'Save Changes'
first(:button, 'Save Changes').click
expect(page.find("#status-message")).to have_content "Changes saved."
p.reload

View File

@@ -61,14 +61,14 @@ describe "BulkProducts service", ->
clonedProduct =
id: 17
spyOn(BulkProducts, "addProducts")
spyOn(BulkProducts, "insertProductAfter")
BulkProducts.products = [originalProduct]
$httpBackend.expectGET("/admin/products/oranges/clone.json").respond 200,
product: clonedProduct
$httpBackend.expectGET("/api/products/17?template=bulk_show").respond 200, clonedProduct
BulkProducts.cloneProduct BulkProducts.products[0]
$httpBackend.flush()
expect(BulkProducts.addProducts).toHaveBeenCalledWith [clonedProduct]
expect(BulkProducts.insertProductAfter).toHaveBeenCalledWith originalProduct, clonedProduct
describe "preparing products", ->

View File

@@ -215,6 +215,7 @@ describe "filtering products for submission to database", ->
variant_unit_scale: 1
variant_unit_name: 'loaf'
available_on: available_on
tax_category_id: null
master_attributes:
id: 2
unit_value: 250
@@ -238,6 +239,7 @@ describe "AdminProductEditCtrl", ->
module ($provide)->
$provide.value "producers", []
$provide.value "taxons", []
$provide.value "tax_categories", []
$provide.value 'SpreeApiKey', 'API_KEY'
null