mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-12 03:50:22 +00:00
Merge branch 'master' of github.com:openfoodfoundation/openfoodnetwork into bulk-product-edit
This commit is contained in:
@@ -146,15 +146,18 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
|
||||
|
||||
$scope.deleteVariant = (product, variant) ->
|
||||
if !$scope.variantSaved(variant)
|
||||
$scope.removeVariant(product, variant)
|
||||
if product.variants.length > 1
|
||||
if !$scope.variantSaved(variant)
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
if confirm("Are you sure?")
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
|
||||
).success (data) ->
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
if confirm("Are you sure?")
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
|
||||
).success (data) ->
|
||||
$scope.removeVariant(product, variant)
|
||||
alert("The last variant cannot be deleted!")
|
||||
|
||||
$scope.removeVariant = (product, variant) ->
|
||||
product.variants.splice product.variants.indexOf(variant), 1
|
||||
|
||||
@@ -5,6 +5,13 @@ angular.module("admin.products")
|
||||
$scope.placeholder_text = ""
|
||||
|
||||
$scope.$watchCollection '[product.variant_unit_with_scale, product.master.unit_value_with_description]', ->
|
||||
$scope.processVariantUnitWithScale()
|
||||
$scope.processUnitValueWithDescription()
|
||||
$scope.placeholder_text = new OptionValueNamer($scope.product.master).name()
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
$scope.processVariantUnitWithScale = ->
|
||||
if $scope.product.variant_unit_with_scale
|
||||
match = $scope.product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
|
||||
if match
|
||||
@@ -16,18 +23,15 @@ angular.module("admin.products")
|
||||
else
|
||||
$scope.product.variant_unit = $scope.product.variant_unit_scale = null
|
||||
|
||||
$scope.processUnitValueWithDescription = ->
|
||||
if $scope.product.master.hasOwnProperty("unit_value_with_description")
|
||||
match = $scope.product.master.unit_value_with_description.match(/^([\d\.]+(?= |$)|)( |)(.*)$/)
|
||||
match = $scope.product.master.unit_value_with_description.match(/^([\d\.]+(?= *|$)|)( *)(.*)$/)
|
||||
if match
|
||||
$scope.product.master.unit_value = parseFloat(match[1])
|
||||
$scope.product.master.unit_value = null if isNaN($scope.product.master.unit_value)
|
||||
$scope.product.master.unit_value *= $scope.product.variant_unit_scale if $scope.product.master.unit_value && $scope.product.variant_unit_scale
|
||||
$scope.product.master.unit_description = match[3]
|
||||
|
||||
$scope.placeholder_text = new OptionValueNamer($scope.product.master).name()
|
||||
|
||||
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
|
||||
|
||||
$scope.hasVariants = (product) ->
|
||||
Object.keys(product.variants).length > 0
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Search, FilterSelectorsService) ->
|
||||
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Search, FilterSelectorsService, EnterpriseModal) ->
|
||||
$scope.totalActive = FilterSelectorsService.totalActive
|
||||
$scope.clearAll = FilterSelectorsService.clearAll
|
||||
$scope.filterText = FilterSelectorsService.filterText
|
||||
$scope.FilterSelectorsService = FilterSelectorsService
|
||||
$scope.query = Search.search()
|
||||
$scope.openModal = EnterpriseModal.open
|
||||
$scope.activeTaxons = []
|
||||
$scope.show_profiles = false
|
||||
$scope.filtersActive = false
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
Darkswarm.controller "GroupsCtrl", ($scope, Groups, $anchorScroll, $rootScope) ->
|
||||
$scope.Groups = Groups
|
||||
$scope.order = 'position'
|
||||
|
||||
#$rootScope.$on "$locationChangeSuccess", (newRoute, oldRoute) ->
|
||||
#$anchorScroll()
|
||||
#
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, Navigation, $location, $templateCache, CurrentHub) ->
|
||||
$scope.toggle = ->
|
||||
HashNavigation.toggle $scope.hub.hash
|
||||
$scope.toggle = (e) ->
|
||||
HashNavigation.toggle $scope.hub.hash if !angular.element(e.target).inheritedData('is-link')
|
||||
|
||||
$scope.open = ->
|
||||
HashNavigation.active $scope.hub.hash
|
||||
|
||||
@@ -249,3 +249,18 @@ span.required {
|
||||
color: red;
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
table td.actions {
|
||||
.icon-trash, .icon-edit, icon-copy {
|
||||
&.disabled {
|
||||
border-color: #d0d0d0;
|
||||
color: #c0c0c0;
|
||||
background-color: #fafafa;
|
||||
&:hover {
|
||||
border-color: #a5a5a5;
|
||||
color: #a5a5a5;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,24 @@
|
||||
.active_table_row:nth-child(2)
|
||||
padding-bottom: 0.75rem
|
||||
|
||||
|
||||
.producers-list
|
||||
li.more-producers-link
|
||||
.less
|
||||
display: none
|
||||
a:hover
|
||||
text-decoration: underline
|
||||
li.additional-producer
|
||||
display: none
|
||||
&.show-more-producers
|
||||
li.additional-producer
|
||||
display: block
|
||||
li.more-producers-link
|
||||
.more
|
||||
display: none
|
||||
.less
|
||||
display: block
|
||||
|
||||
//CURRENT hub (shows selected hub)
|
||||
&.current
|
||||
//overwrites active_table
|
||||
@@ -83,6 +101,7 @@
|
||||
.active_table_row:first-child .skinny-head
|
||||
background-color: rgba(255,255,255,0.85)
|
||||
|
||||
|
||||
//INACTIVE - closed hub
|
||||
&.inactive
|
||||
&.closed, &.open
|
||||
|
||||
@@ -9,7 +9,7 @@ module Admin
|
||||
|
||||
def move_up
|
||||
EnterpriseGroup.with_isolation_level_serializable do
|
||||
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
|
||||
@enterprise_group = EnterpriseGroup.find_by_permalink params[:enterprise_group_id]
|
||||
@enterprise_group.move_higher
|
||||
end
|
||||
redirect_to main_app.admin_enterprise_groups_path
|
||||
@@ -17,7 +17,7 @@ module Admin
|
||||
|
||||
def move_down
|
||||
EnterpriseGroup.with_isolation_level_serializable do
|
||||
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
|
||||
@enterprise_group = EnterpriseGroup.find_by_permalink params[:enterprise_group_id]
|
||||
@enterprise_group.move_lower
|
||||
end
|
||||
redirect_to main_app.admin_enterprise_groups_path
|
||||
@@ -33,6 +33,12 @@ module Admin
|
||||
end
|
||||
alias_method_chain :build_resource, :address
|
||||
|
||||
# Overriding method on Spree's resource controller,
|
||||
# so that resources are found using permalink
|
||||
def find_resource
|
||||
EnterpriseGroup.find_by_permalink(params[:id])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_data
|
||||
|
||||
@@ -3,6 +3,7 @@ module Admin
|
||||
before_filter :load_enterprise_set, :only => :index
|
||||
before_filter :load_countries, :except => [:index, :set_sells, :check_permalink]
|
||||
before_filter :load_methods_and_fees, :only => [:new, :edit, :update, :create]
|
||||
before_filter :load_groups, :only => [:new, :edit, :update, :create]
|
||||
before_filter :load_taxons, :only => [:new, :edit, :update, :create]
|
||||
before_filter :check_can_change_sells, only: :update
|
||||
before_filter :check_can_change_bulk_sells, only: :bulk_update
|
||||
@@ -127,6 +128,10 @@ module Admin
|
||||
@enterprise_fees = EnterpriseFee.managed_by(spree_current_user).for_enterprise(@enterprise).order(:fee_type, :name).all
|
||||
end
|
||||
|
||||
def load_groups
|
||||
@groups = EnterpriseGroup.managed_by(spree_current_user) | @enterprise.groups
|
||||
end
|
||||
|
||||
def load_taxons
|
||||
@taxons = Spree::Taxon.order(:name)
|
||||
end
|
||||
|
||||
@@ -7,6 +7,6 @@ class GroupsController < BaseController
|
||||
end
|
||||
|
||||
def show
|
||||
@group = EnterpriseGroup.find params[:id]
|
||||
@group = EnterpriseGroup.find_by_permalink(params[:id]) || EnterpriseGroup.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -4,7 +4,7 @@ Spree::Admin::VariantsController.class_eval do
|
||||
def search
|
||||
search_params = { :product_name_cont => params[:q], :sku_cont => params[:q] }
|
||||
|
||||
@variants = Spree::Variant.ransack(search_params.merge(:m => 'or')).result
|
||||
@variants = Spree::Variant.where(is_master: false).ransack(search_params.merge(:m => 'or')).result
|
||||
|
||||
if params[:order_cycle_id].present?
|
||||
order_cycle = OrderCycle.find params[:order_cycle_id]
|
||||
|
||||
@@ -299,7 +299,7 @@ class Enterprise < ActiveRecord::Base
|
||||
test_permalink = test_permalink.parameterize
|
||||
test_permalink = "my-enterprise" if test_permalink.blank?
|
||||
existing = Enterprise.select(:permalink).order(:permalink).where("permalink LIKE ?", "#{test_permalink}%").map(&:permalink)
|
||||
if existing.empty?
|
||||
unless existing.include?(test_permalink)
|
||||
test_permalink
|
||||
else
|
||||
used_indices = existing.map do |p|
|
||||
|
||||
@@ -16,8 +16,12 @@ class EnterpriseGroup < ActiveRecord::Base
|
||||
validates :name, presence: true
|
||||
validates :description, presence: true
|
||||
|
||||
before_validation :sanitize_permalink
|
||||
validates :permalink, uniqueness: true, presence: true
|
||||
|
||||
attr_accessible :name, :description, :long_description, :on_front_page, :enterprise_ids
|
||||
attr_accessible :owner_id
|
||||
attr_accessible :permalink
|
||||
attr_accessible :logo, :promo_image
|
||||
attr_accessible :address_attributes
|
||||
attr_accessible :email, :website, :facebook, :instagram, :linkedin, :twitter
|
||||
@@ -71,4 +75,31 @@ class EnterpriseGroup < ActiveRecord::Base
|
||||
address.zipcode.sub!(/^undefined$/, '')
|
||||
end
|
||||
|
||||
def to_param
|
||||
permalink
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.find_available_value(existing, requested)
|
||||
return requested unless existing.include?(requested)
|
||||
used_indices = existing.map do |p|
|
||||
p.slice!(/^#{requested}/)
|
||||
p.match(/^\d+$/).to_s.to_i
|
||||
end
|
||||
options = (1..used_indices.length + 1).to_a - used_indices
|
||||
requested + options.first.to_s
|
||||
end
|
||||
|
||||
def find_available_permalink(requested)
|
||||
existing = self.class.where(id: !id).where("permalink LIKE ?", "#{requested}%").pluck(:permalink)
|
||||
self.class.find_available_value(existing, requested)
|
||||
end
|
||||
|
||||
def sanitize_permalink
|
||||
if permalink.blank? || permalink_changed?
|
||||
requested = permalink.presence || permalink_was.presence || name.presence || 'group'
|
||||
self.permalink = find_available_permalink(requested.parameterize)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,17 +23,18 @@ Spree::Product.class_eval do
|
||||
attr_accessible :variant_unit, :variant_unit_scale, :variant_unit_name, :unit_value
|
||||
attr_accessible :inherits_properties, :sku
|
||||
|
||||
validates_associated :master, message: "^Price and On Hand must be valid"
|
||||
# validates_presence_of :variants, unless: :new_record?, message: "Product must have at least one variant"
|
||||
validates_presence_of :supplier
|
||||
validates :primary_taxon, presence: { message: "^Product Category can't be blank" }
|
||||
validates :tax_category_id, presence: { message: "^Tax Category can't be blank" }, if: "Spree::Config.products_require_tax_category"
|
||||
|
||||
validates_presence_of :variant_unit, if: :has_variants?
|
||||
validates_presence_of :variant_unit
|
||||
validates_presence_of :variant_unit_scale,
|
||||
if: -> p { %w(weight volume).include? p.variant_unit }
|
||||
validates_presence_of :variant_unit_name,
|
||||
if: -> p { p.variant_unit == 'items' }
|
||||
|
||||
after_save :ensure_standard_variant
|
||||
after_initialize :set_available_on_to_now, :if => :new_record?
|
||||
after_save :update_units
|
||||
after_touch :touch_distributors
|
||||
@@ -215,4 +216,31 @@ Spree::Product.class_eval do
|
||||
Spree::OptionType.where('name LIKE ?', 'unit_%%')
|
||||
end
|
||||
|
||||
def ensure_standard_variant
|
||||
if master.valid? && variants.empty?
|
||||
variant = self.master.dup
|
||||
variant.product = self
|
||||
variant.is_master = false
|
||||
self.variants << variant
|
||||
end
|
||||
end
|
||||
|
||||
# Override Spree's old save_master method and replace it with the most recent method from spree repository
|
||||
# This fixes any problems arising from failing master saves, without the need for a validates_associated on
|
||||
# master, while giving us more specific errors as to why saving failed
|
||||
def save_master
|
||||
begin
|
||||
if master && (master.changed? || master.new_record? || (master.default_price && (master.default_price.changed? || master.default_price.new_record?)))
|
||||
master.save!
|
||||
end
|
||||
|
||||
# If the master cannot be saved, the Product object will get its errors
|
||||
# and will be destroyed
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
master.errors.each do |att, error|
|
||||
self.errors.add(att, error)
|
||||
end
|
||||
raise
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ class Spree::ProductSet < ModelSet
|
||||
if e.nil?
|
||||
@klass.new(attributes).save unless @reject_if.andand.call(attributes)
|
||||
else
|
||||
e.update_attributes(attributes.except(:id, :variants_attributes, :master_attributes)) and
|
||||
( attributes.except(:id, :variants_attributes, :master_attributes).present? ? e.update_attributes(attributes.except(:id, :variants_attributes, :master_attributes)) : true) and
|
||||
(attributes[:variants_attributes] ? update_variants_attributes(e, attributes[:variants_attributes]) : true ) and
|
||||
(attributes[:master_attributes] ? update_variant(e, attributes[:master_attributes]) : true )
|
||||
end
|
||||
|
||||
@@ -13,12 +13,10 @@ Spree::Variant.class_eval do
|
||||
accepts_nested_attributes_for :images
|
||||
|
||||
validates_presence_of :unit_value,
|
||||
if: -> v { %w(weight volume).include? v.product.andand.variant_unit },
|
||||
unless: :is_master
|
||||
if: -> v { %w(weight volume).include? v.product.andand.variant_unit }
|
||||
|
||||
validates_presence_of :unit_description,
|
||||
if: -> v { v.product.andand.variant_unit.present? && v.unit_value.nil? },
|
||||
unless: :is_master
|
||||
if: -> v { v.product.andand.variant_unit.present? && v.unit_value.nil? }
|
||||
|
||||
before_validation :update_weight_from_unit_value, if: -> v { v.product.present? }
|
||||
after_save :update_units
|
||||
@@ -111,9 +109,15 @@ Spree::Variant.class_eval do
|
||||
end
|
||||
|
||||
def delete
|
||||
transaction do
|
||||
self.update_column(:deleted_at, Time.now)
|
||||
ExchangeVariant.where(variant_id: self).destroy_all
|
||||
if product.variants == [self] # Only variant left on product
|
||||
errors.add :product, "must have at least one variant"
|
||||
false
|
||||
else
|
||||
transaction do
|
||||
self.update_column(:deleted_at, Time.now)
|
||||
ExchangeVariant.where(variant_id: self).destroy_all
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -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})
|
||||
@@ -19,3 +19,8 @@
|
||||
= f.label :enterprise_ids, 'Enterprises'
|
||||
%br/
|
||||
= f.collection_select :enterprise_ids, @enterprises, :id, :name, {}, {class: "select2 fullwidth", multiple: true}
|
||||
|
||||
= f.field_container :permalink do
|
||||
= f.label :permalink, "Permalink (unique, no spaces)"
|
||||
%br/
|
||||
= f.text_field :permalink
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
%span.required *
|
||||
.eight.columns.omega
|
||||
= f.text_field :name, { placeholder: "eg. Professor Plum's Biodynamic Truffles" }
|
||||
.row
|
||||
.alpha.eleven.columns
|
||||
.three.columns.alpha
|
||||
= f.label :group_ids, 'Groups'
|
||||
.with-tip{'data-powertip' => "Select any groups or regions that you are a member of. This will help customers find your enterprise."}
|
||||
%a What's this?
|
||||
|
||||
.eight.columns.omega
|
||||
= f.collection_select :group_ids, EnterpriseGroup.all, :id, :name, {}, class: "select2 fullwidth", multiple: true, placeholder: "Start typing to search available groups..."
|
||||
- if @groups.present?
|
||||
.row
|
||||
.alpha.eleven.columns
|
||||
.three.columns.alpha
|
||||
= f.label :group_ids, 'Groups'
|
||||
.with-tip{'data-powertip' => "Select any groups or regions that you are a member of. This will help customers find your enterprise."}
|
||||
%a What's this?
|
||||
.eight.columns.omega
|
||||
= f.collection_select :group_ids, @groups, :id, :name, {}, class: "select2 fullwidth", multiple: true, placeholder: "Start typing to search available groups..."
|
||||
|
||||
.row
|
||||
.three.columns.alpha
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
.row.pad-top{bindonce: true}
|
||||
.small-12.medium-6.columns
|
||||
.groups-header
|
||||
%a{"bo-href-i" => "/groups/{{group.id}}"}
|
||||
%a{"bo-href-i" => "/groups/{{group.permalink}}"}
|
||||
%i.ofn-i_035-groups
|
||||
%span.group-name{"bo-text" => "group.name"}
|
||||
.small-3.medium-2.columns
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.row.active_table_row{"ng-show" => "open()", "ng-click" => "toggle()", "ng-class" => "{'open' : !ofn-i_032-closed-sign()}"}
|
||||
.row.active_table_row{"ng-show" => "open()", "ng-click" => "toggle($event)", "ng-class" => "{'open' : !ofn-i_032-closed-sign()}"}
|
||||
.columns.small-12.medium-6.large-5.fat
|
||||
%div{"bo-if" => "hub.taxons"}
|
||||
%label Shop for
|
||||
@@ -21,8 +21,20 @@
|
||||
.columns.small-12.medium-3.large-5.fat
|
||||
%div{"bo-if" => "hub.producers"}
|
||||
%label Our producers
|
||||
%ul.small-block-grid-2.medium-block-grid-1.large-block-grid-2
|
||||
%li{"ng-repeat" => "enterprise in hub.producers"}
|
||||
%ul.small-block-grid-2.medium-block-grid-1.large-block-grid-2{"ng-class" => "{'show-more-producers' : toggleMoreProducers}", "class" => "producers-list"}
|
||||
%li{"ng-repeat" => "enterprise in hub.producers | limitTo:7"}
|
||||
%enterprise-modal
|
||||
%i.ofn-i_036-producers
|
||||
%span{"bo-text" => "enterprise.name"}
|
||||
%li{"data-is-link" => "true", "class" => "more-producers-link", "bo-show" => "hub.producers.length>7"}
|
||||
%a{"ng-click" => "toggleMoreProducers=!toggleMoreProducers"}
|
||||
.more
|
||||
+
|
||||
%span{"bo-text" => "hub.producers.length-7"}
|
||||
More
|
||||
.less
|
||||
Show less
|
||||
%li{"ng-repeat" => "enterprise in hub.producers.slice(7,hub.producers.length)", "class" => "additional-producer"}
|
||||
%enterprise-modal
|
||||
%i.ofn-i_036-producers
|
||||
%span{"bo-text" => "enterprise.name"}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.row.active_table_row{"ng-if" => "hub.is_distributor", "ng-click" => "toggle()", "ng-class" => "{'closed' : !open(), 'is_distributor' : producer.is_distributor}", bindonce: true}
|
||||
.row.active_table_row{"ng-if" => "hub.is_distributor", "ng-click" => "toggle($event)", "ng-class" => "{'closed' : !open(), 'is_distributor' : producer.is_distributor}", bindonce: true}
|
||||
|
||||
.columns.small-12.medium-6.large-5.skinny-head
|
||||
%a.hub{"bo-href" => "hub.path", "ng-class" => "{primary: hub.active, secondary: !hub.active}", "ofn-empties-cart" => "hub"}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
collection @groups
|
||||
attributes :id, :name, :position, :description, :long_description, :email, :website, :facebook, :instagram, :linkedin, :twitter
|
||||
attributes :id, :permalink, :name, :position, :description, :long_description, :email, :website, :facebook, :instagram, :linkedin, :twitter
|
||||
|
||||
child enterprises: :enterprises do
|
||||
attributes :id
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.row.active_table_row{"ng-if" => "open()", "ng-click" => "toggle()", "ng-class" => "{'open' : !ofn-i_032-closed-sign()}"}
|
||||
.row.active_table_row{"ng-if" => "open()", "ng-click" => "toggle($event)", "ng-class" => "{'open' : !ofn-i_032-closed-sign()}"}
|
||||
|
||||
.columns.small-12.medium-7.large-7.fat
|
||||
/ Will add in long description available once clean up HTML formatting producer.long_description
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.row.active_table_row{"ng-click" => "toggle()", "ng-class" => "{'closed' : !open(), 'is_distributor' : producer.is_distributor}"}
|
||||
.row.active_table_row{"ng-click" => "toggle($event)", "ng-class" => "{'closed' : !open(), 'is_distributor' : producer.is_distributor}"}
|
||||
.columns.small-12.medium-4.large-4.skinny-head
|
||||
%span{"bo-if" => "producer.is_distributor" }
|
||||
%a.is_distributor{"bo-href" => "producer.path" }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
.panel
|
||||
.row
|
||||
.small-12.large-4.columns
|
||||
- if current_distributor.address.address1 || current_distributor.address.address2 || current_distributor.address.city || current_distributor.address.state || current_distributor.address.zipcode
|
||||
- if current_distributor.address.address1 || current_distributor.address.address2 || current_distributor.address.city || current_distributor.address.state || current_distributor.address.zipcode
|
||||
%div.center
|
||||
.header Address
|
||||
%strong=current_distributor.name
|
||||
@@ -49,7 +49,7 @@
|
||||
- unless current_distributor.linkedin.blank?
|
||||
%span
|
||||
%a{href: "http://#{current_distributor.linkedin}", target: "_blank" }
|
||||
%i.ofn-i_042-linkedin
|
||||
%i.ofn-i_042-linkedin
|
||||
/ = current_distributor.linkedin
|
||||
|
||||
- unless current_distributor.instagram.blank?
|
||||
|
||||
@@ -9,5 +9,5 @@
|
||||
%ul.bullet-list
|
||||
- for group in current_distributor.groups
|
||||
%li
|
||||
%a{href: main_app.groups_path + "/#/#group#{group.id}"}
|
||||
%a{href: main_app.groups_path + "/#{group.permalink}"}
|
||||
= group.name
|
||||
|
||||
@@ -26,4 +26,4 @@
|
||||
%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)', :class => "delete-variant icon-trash no-text" }
|
||||
%a{ 'ng-click' => 'deleteVariant(product,variant)', "ng-class" => '{disabled: product.variants.length < 2}', :class => "delete-variant icon-trash no-text" }
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
class AddStandardVariantToProducts < ActiveRecord::Migration
|
||||
def up
|
||||
# Make sure that all products have a variant_unit
|
||||
Spree::Product.where("variant_unit IS NULL OR variant_unit = ''").update_all(variant_unit: "items", variant_unit_name: "each")
|
||||
|
||||
# Find products without any standard variants
|
||||
products_with_only_master = Spree::Product.includes(:variants).where('spree_variants.id IS NULL').select('DISTINCT spree_products.*')
|
||||
|
||||
products_with_only_master.each do |product|
|
||||
# Add a unit_value to the master variant if it doesn't have one
|
||||
if product.unit_value.blank?
|
||||
if product.variant_unit == "weight" && match = product.unit_description.andand.match(/^(\d+(\.\d*)?)(k?g) ?(.*)$/)
|
||||
scale = (match[3] == "kg" ? 1000 : 1)
|
||||
product.unit_value = (match[1].to_i*scale)
|
||||
product.unit_description = match[4]
|
||||
product.save!
|
||||
else
|
||||
unless product.variant_unit == "items" && product.unit_description.present?
|
||||
product.unit_value = 1
|
||||
product.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Run the callback to add a copy of the master variant as a standard variant
|
||||
product.send(:ensure_standard_variant)
|
||||
|
||||
existing_master = product.master
|
||||
new_variant = product.variants.first
|
||||
|
||||
# Replace any relevant references to the master variant with the new standard variant
|
||||
|
||||
# Inventory Units
|
||||
# Strategy: do nothing to inventory units pertaining to existing_master,
|
||||
# new inventory units will be created with reference to new_variant
|
||||
|
||||
# Line Items
|
||||
# Strategy: do nothing to line items pertaining to existing_master,
|
||||
# new line items will be created with reference to new_variant
|
||||
|
||||
# Option Values
|
||||
# Strategy: add all option values on existing_master to new_variant, and keep on existing_master
|
||||
option_values = existing_master.option_values
|
||||
option_values.each do |option_value|
|
||||
variant_ids = option_value.variant_ids
|
||||
variant_ids << new_variant.id
|
||||
option_value.update_attributes(variant_ids: variant_ids)
|
||||
end
|
||||
|
||||
# Prices
|
||||
# Strategy: duplicate all prices on existing_master and assign them to new_variant
|
||||
existing_prices = existing_master.prices
|
||||
existing_prices.each do |price|
|
||||
new_variant.prices << price.dup
|
||||
end
|
||||
|
||||
# Exchange Variants
|
||||
# Strategy: Replace all references to existing master in exchanges with new_variant
|
||||
exchange_variants = ExchangeVariant.where(variant_id: existing_master.id)
|
||||
exchange_variants.update_all(variant_id: new_variant.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
26
db/migrate/20150527004427_add_permalink_to_groups.rb
Normal file
26
db/migrate/20150527004427_add_permalink_to_groups.rb
Normal file
@@ -0,0 +1,26 @@
|
||||
class AddPermalinkToGroups < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :enterprise_groups, :permalink, :string
|
||||
|
||||
EnterpriseGroup.reset_column_information
|
||||
|
||||
EnterpriseGroup.all.each do |group|
|
||||
counter = 1
|
||||
permalink = group.name.parameterize
|
||||
permalink = "my-group-name" if permalink == ""
|
||||
while EnterpriseGroup.find_by_permalink(permalink) do
|
||||
permalink = group.name.parameterize + counter.to_s
|
||||
counter += 1
|
||||
end
|
||||
|
||||
group.update_column :permalink, permalink
|
||||
end
|
||||
|
||||
change_column :enterprise_groups, :permalink, :string, null: false
|
||||
add_index :enterprise_groups, :permalink, :unique => true
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :enterprise_groups, :permalink
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20150424151117) do
|
||||
ActiveRecord::Schema.define(:version => 20150527004427) do
|
||||
|
||||
create_table "adjustment_metadata", :force => true do |t|
|
||||
t.integer "adjustment_id"
|
||||
@@ -236,10 +236,12 @@ ActiveRecord::Schema.define(:version => 20150424151117) do
|
||||
t.string "linkedin", :default => "", :null => false
|
||||
t.string "twitter", :default => "", :null => false
|
||||
t.integer "owner_id"
|
||||
t.string "permalink", :null => false
|
||||
end
|
||||
|
||||
add_index "enterprise_groups", ["address_id"], :name => "index_enterprise_groups_on_address_id"
|
||||
add_index "enterprise_groups", ["owner_id"], :name => "index_enterprise_groups_on_owner_id"
|
||||
add_index "enterprise_groups", ["permalink"], :name => "index_enterprise_groups_on_permalink", :unique => true
|
||||
|
||||
create_table "enterprise_groups_enterprises", :id => false, :force => true do |t|
|
||||
t.integer "enterprise_group_id"
|
||||
@@ -619,9 +621,9 @@ ActiveRecord::Schema.define(:version => 20150424151117) do
|
||||
t.string "email"
|
||||
t.text "special_instructions"
|
||||
t.integer "distributor_id"
|
||||
t.integer "order_cycle_id"
|
||||
t.string "currency"
|
||||
t.string "last_ip_address"
|
||||
t.integer "order_cycle_id"
|
||||
t.integer "cart_id"
|
||||
end
|
||||
|
||||
|
||||
@@ -75,8 +75,9 @@ module OpenFoodNetwork
|
||||
it 'should add variant to new order and return the order' do
|
||||
product1.distributors << distributor
|
||||
product1.save
|
||||
variant = product1.variants.first
|
||||
|
||||
put :add_variant, { cart_id: cart, variant_id: product1.master.id, quantity: (product1.master.on_hand-1), distributor_id: distributor, order_cycle_id: nil, max_quantity: nil }
|
||||
put :add_variant, { cart_id: cart, variant_id: variant.id, quantity: (variant.on_hand-1), distributor_id: distributor, order_cycle_id: nil, max_quantity: nil }
|
||||
|
||||
cart.orders.size.should == 1
|
||||
cart.orders.first.line_items.size.should == 1
|
||||
|
||||
@@ -112,10 +112,10 @@ describe ShopController do
|
||||
let!(:p4) { create(:product, name: "jkl", primary_taxon_id: t1.id) }
|
||||
|
||||
before do
|
||||
exchange.variants << p1.master
|
||||
exchange.variants << p2.master
|
||||
exchange.variants << p3.master
|
||||
exchange.variants << p4.master
|
||||
exchange.variants << p1.variants.first
|
||||
exchange.variants << p2.variants.first
|
||||
exchange.variants << p3.variants.first
|
||||
exchange.variants << p4.variants.first
|
||||
end
|
||||
|
||||
it "sorts products by the distributor's preferred taxon list" do
|
||||
@@ -136,19 +136,20 @@ describe ShopController do
|
||||
context "RABL tests" do
|
||||
render_views
|
||||
let(:product) { create(:product) }
|
||||
let(:variant) { product.variants.first }
|
||||
|
||||
before do
|
||||
exchange.variants << product.master
|
||||
exchange.variants << variant
|
||||
controller.stub(:current_order_cycle).and_return order_cycle
|
||||
end
|
||||
|
||||
it "only returns products for the current order cycle" do
|
||||
xhr :get, :products
|
||||
response.body.should have_content product.name
|
||||
end
|
||||
|
||||
it "doesn't return products not in stock" do
|
||||
product.update_attribute(:on_demand, false)
|
||||
product.master.update_attribute(:count_on_hand, 0)
|
||||
variant.update_attribute(:count_on_hand, 0)
|
||||
xhr :get, :products
|
||||
response.body.should_not have_content product.name
|
||||
end
|
||||
|
||||
@@ -143,7 +143,7 @@ describe Spree::Admin::OrdersController do
|
||||
end
|
||||
|
||||
it "only displays line items from orders for which my enterprise is the order_cycle coorinator" do
|
||||
json_response.map{ |order| order['line_items'] }.flatten.map{ |line_item| line_item["id"] }.sort.should == [line_item1.id, line_item2.id, line_item3.id].sort
|
||||
json_response.map{ |order| order['line_items'] }.flatten.map{ |line_item| line_item["id"] }.should match_array [line_item1.id, line_item2.id, line_item3.id]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -159,7 +159,7 @@ describe Spree::Admin::OrdersController do
|
||||
end
|
||||
|
||||
it "only displays line items from orders for which my enterprise is a distributor" do
|
||||
json_response.map{ |order| order['line_items'] }.flatten.map{ |line_item| line_item["id"] }.sort.should == [line_item1.id, line_item2.id].sort
|
||||
json_response.map{ |order| order['line_items'] }.flatten.map{ |line_item| line_item["id"] }.should match_array [line_item1.id, line_item2.id]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -170,17 +170,17 @@ describe Spree::Admin::ReportsController do
|
||||
|
||||
it "should build distributors for the current user" do
|
||||
spree_get :products_and_inventory
|
||||
assigns(:distributors).sort.should == [c1, c2, d1, d2, d3].sort
|
||||
assigns(:distributors).should match_array [c1, c2, d1, d2, d3]
|
||||
end
|
||||
|
||||
it "builds suppliers for the current user" do
|
||||
spree_get :products_and_inventory
|
||||
assigns(:suppliers).sort.should == [s1, s2, s3].sort
|
||||
assigns(:suppliers).should match_array [s1, s2, s3]
|
||||
end
|
||||
|
||||
it "builds order cycles for the current user" do
|
||||
spree_get :products_and_inventory
|
||||
assigns(:order_cycles).sort.should == [ocB, ocA].sort
|
||||
assigns(:order_cycles).should match_array [ocB, ocA]
|
||||
end
|
||||
|
||||
it "assigns report types" do
|
||||
@@ -211,17 +211,17 @@ describe Spree::Admin::ReportsController do
|
||||
|
||||
it "should build distributors for the current user" do
|
||||
spree_get :customers
|
||||
assigns(:distributors).sort.should == [c1, c2, d1, d2, d3].sort
|
||||
assigns(:distributors).should match_array [c1, c2, d1, d2, d3]
|
||||
end
|
||||
|
||||
it "builds suppliers for the current user" do
|
||||
spree_get :customers
|
||||
assigns(:suppliers).sort.should == [s1, s2, s3].sort
|
||||
assigns(:suppliers).should match_array [s1, s2, s3]
|
||||
end
|
||||
|
||||
it "builds order cycles for the current user" do
|
||||
spree_get :customers
|
||||
assigns(:order_cycles).sort.should == [ocB, ocA].sort
|
||||
assigns(:order_cycles).should match_array [ocB, ocA]
|
||||
end
|
||||
|
||||
it "assigns report types" do
|
||||
|
||||
@@ -8,29 +8,31 @@ module Spree
|
||||
describe "search action" do
|
||||
let!(:p1) { create(:simple_product, name: 'Product 1') }
|
||||
let!(:p2) { create(:simple_product, name: 'Product 2') }
|
||||
let!(:vo) { create(:variant_override, variant: p1.master, hub: d, count_on_hand: 44) }
|
||||
let!(:v1) { p1.variants.first }
|
||||
let!(:v2) { p2.variants.first }
|
||||
let!(:vo) { create(:variant_override, variant: v1, hub: d, count_on_hand: 44) }
|
||||
let!(:d) { create(:distributor_enterprise) }
|
||||
let!(:oc) { create(:simple_order_cycle, distributors: [d], variants: [p1.master]) }
|
||||
let!(:oc) { create(:simple_order_cycle, distributors: [d], variants: [v1]) }
|
||||
|
||||
it "filters by distributor" do
|
||||
spree_get :search, q: 'Prod', distributor_id: d.id.to_s
|
||||
assigns(:variants).should == [p1.master]
|
||||
assigns(:variants).should == [v1]
|
||||
end
|
||||
|
||||
it "applies variant overrides" do
|
||||
spree_get :search, q: 'Prod', distributor_id: d.id.to_s
|
||||
assigns(:variants).should == [p1.master]
|
||||
assigns(:variants).should == [v1]
|
||||
assigns(:variants).first.count_on_hand.should == 44
|
||||
end
|
||||
|
||||
it "filters by order cycle" do
|
||||
spree_get :search, q: 'Prod', order_cycle_id: oc.id.to_s
|
||||
assigns(:variants).should == [p1.master]
|
||||
assigns(:variants).should == [v1]
|
||||
end
|
||||
|
||||
it "does not filter when no distributor or order cycle is specified" do
|
||||
spree_get :search, q: 'Prod'
|
||||
assigns(:variants).sort.should == [p1.master, p2.master].sort
|
||||
assigns(:variants).should match_array [v1, v2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,7 +45,7 @@ FactoryGirl.define do
|
||||
image = File.open(File.expand_path('../../app/assets/images/logo.jpg', __FILE__))
|
||||
Spree::Image.create({:viewable_id => product.master.id, :viewable_type => 'Spree::Variant', :alt => "position 1", :attachment => image, :position => 1})
|
||||
|
||||
exchange.variants << product.master
|
||||
exchange.variants << product.variants.first
|
||||
end
|
||||
|
||||
variants = [ex1, ex2].map(&:variants).flatten
|
||||
@@ -97,7 +97,6 @@ FactoryGirl.define do
|
||||
factory :enterprise, :class => Enterprise do
|
||||
owner { FactoryGirl.create :user }
|
||||
sequence(:name) { |n| "Enterprise #{n}" }
|
||||
sequence(:permalink) { |n| "enterprise#{n}" }
|
||||
sells 'any'
|
||||
description 'enterprise'
|
||||
long_description '<p>Hello, world!</p><p>This is a paragraph.</p>'
|
||||
@@ -135,6 +134,7 @@ FactoryGirl.define do
|
||||
|
||||
factory :enterprise_group, :class => EnterpriseGroup do
|
||||
name 'Enterprise group'
|
||||
sequence(:permalink) { |n| "group#{n}" }
|
||||
description 'this is a group'
|
||||
on_front_page false
|
||||
address { FactoryGirl.build(:address) }
|
||||
@@ -219,6 +219,10 @@ end
|
||||
|
||||
|
||||
FactoryGirl.modify do
|
||||
factory :base_product do
|
||||
unit_value 1
|
||||
unit_description ''
|
||||
end
|
||||
factory :product do
|
||||
primary_taxon { Spree::Taxon.first || FactoryGirl.create(:taxon) }
|
||||
end
|
||||
|
||||
@@ -53,62 +53,18 @@ feature %q{
|
||||
expect(page).to have_field "available_on", with: p2.available_on.strftime("%F %T")
|
||||
end
|
||||
|
||||
it "displays a price input for each product without variants (ie. for master variant)" do
|
||||
p1 = FactoryGirl.create(:product)
|
||||
p2 = FactoryGirl.create(:product)
|
||||
p3 = FactoryGirl.create(:product)
|
||||
v = FactoryGirl.create(:variant, product: p3)
|
||||
|
||||
p1.update_attribute :price, 22.0
|
||||
p2.update_attribute :price, 44.0
|
||||
p3.update_attribute :price, 66.0
|
||||
it "displays an on hand count in a span for each product" do
|
||||
p1 = FactoryGirl.create(:product, on_hand: 15)
|
||||
v1 = p1.variants.first
|
||||
v1.on_hand = 4
|
||||
v1.save!
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_field "price", with: "22.0"
|
||||
expect(page).to have_field "price", with: "44.0"
|
||||
expect(page).to have_no_field "price", with: "66.0", visible: true
|
||||
end
|
||||
|
||||
it "displays an on hand count input for each product (ie. for master variant) if no regular variants exist" do
|
||||
p1 = FactoryGirl.create(:product)
|
||||
p2 = FactoryGirl.create(:product)
|
||||
p1.on_hand = 15
|
||||
p2.on_hand = 12
|
||||
p1.save!
|
||||
p2.save!
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_no_selector "span[name='on_hand']", text: "0"
|
||||
expect(page).to have_field "on_hand", with: "15"
|
||||
expect(page).to have_field "on_hand", with: "12"
|
||||
end
|
||||
|
||||
it "displays an on hand count in a span for each product (ie. for master variant) 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.on_hand = 15
|
||||
p2.on_hand = 12
|
||||
p1.save!
|
||||
p2.save!
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_no_field "on_hand", with: "15"
|
||||
expect(page).to have_selector "span[name='on_hand']", text: "4"
|
||||
expect(page).to have_field "on_hand", with: "12"
|
||||
end
|
||||
|
||||
it "displays 'on demand' for the on hand count when the product is available on demand" do
|
||||
p1 = FactoryGirl.create(:product, on_demand: true)
|
||||
p1.master.on_demand = true; p1.master.save!
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_selector "span[name='on_hand']", text: "On demand"
|
||||
expect(page).to have_no_field "on_hand", visible: true
|
||||
within "#p_#{p1.id}" do
|
||||
expect(page).to have_no_field "on_hand", with: "15"
|
||||
expect(page).to have_selector "span[name='on_hand']", text: "4"
|
||||
end
|
||||
end
|
||||
|
||||
it "displays 'on demand' for any variant that is available on demand" do
|
||||
@@ -170,7 +126,7 @@ feature %q{
|
||||
visit '/admin/products/bulk_edit'
|
||||
all("a.view-variants").each { |e| e.trigger('click') }
|
||||
|
||||
expect(page).to have_selector "span[name='on_hand']", text: "21"
|
||||
expect(page).to have_selector "span[name='on_hand']", text: p1.variants.sum{ |v| v.on_hand }.to_s
|
||||
expect(page).to have_field "variant_on_hand", with: "15"
|
||||
expect(page).to have_field "variant_on_hand", with: "6"
|
||||
end
|
||||
@@ -218,7 +174,9 @@ feature %q{
|
||||
expect(page).to have_content 'NEW PRODUCT'
|
||||
|
||||
fill_in 'product_name', :with => 'Big Bag Of Apples'
|
||||
select(s.name, :from => 'product_supplier_id')
|
||||
select s.name, :from => 'product_supplier_id'
|
||||
select 'Weight (g)', from: 'product_variant_unit_with_scale'
|
||||
fill_in 'product_unit_value_with_description', with: '100'
|
||||
fill_in 'product_price', :with => '10.00'
|
||||
select taxon.name, from: 'product_primary_taxon_id'
|
||||
click_button 'Create'
|
||||
@@ -231,34 +189,25 @@ feature %q{
|
||||
|
||||
scenario "creating new variants" do
|
||||
# Given a product without variants or a unit
|
||||
p = FactoryGirl.create(:product, variant_unit: nil, variant_unit_scale: nil)
|
||||
p = FactoryGirl.create(:product, variant_unit: 'weight', variant_unit_scale: 1000)
|
||||
login_to_admin_section
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
# I should not see an add variant button
|
||||
expect(page).to have_no_selector 'a.add-variant', visible: true
|
||||
|
||||
# When I set the unit
|
||||
select "Weight (kg)", from: "variant_unit_with_scale"
|
||||
|
||||
# I should see an add variant button
|
||||
expect(page).to have_selector 'a.add-variant', visible: true
|
||||
page.find('a.view-variants').trigger('click')
|
||||
|
||||
# When I add three variants
|
||||
page.find('a.add-variant', visible: true).trigger('click')
|
||||
page.find('a.add-variant', visible: true).trigger('click')
|
||||
page.find('a.add-variant', visible: true).trigger('click')
|
||||
|
||||
# They should be added, and should see no edit buttons
|
||||
variant_count = page.all("tr.variant").count
|
||||
expect(variant_count).to eq 3
|
||||
expect(page).to have_no_selector "a.edit-variant", visible: true
|
||||
# They should be added, and should not see edit buttons for new variants
|
||||
expect(page).to have_selector "tr.variant", count: 3
|
||||
expect(page).to have_selector "a.edit-variant", count: 1
|
||||
|
||||
# When I remove two, they should be removed
|
||||
page.all('a.delete-variant').first.click
|
||||
page.all('a.delete-variant').first.click
|
||||
variant_count = page.all("tr.variant").count
|
||||
expect(variant_count).to eq 1
|
||||
expect(page).to have_selector "tr.variant", count: 1
|
||||
|
||||
# When I fill out variant details and hit update
|
||||
fill_in "variant_display_name", with: "Case of 12 Bottles"
|
||||
@@ -266,6 +215,7 @@ feature %q{
|
||||
fill_in "variant_display_as", with: "Case"
|
||||
fill_in "variant_price", with: "4.0"
|
||||
fill_in "variant_on_hand", with: "10"
|
||||
|
||||
first(:button, 'Save Changes').click
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
|
||||
@@ -281,16 +231,12 @@ feature %q{
|
||||
expect(page).to have_selector "a.edit-variant", visible: true
|
||||
end
|
||||
|
||||
|
||||
scenario "updating a product with no variants (except master)" do
|
||||
scenario "updating product attributes" do
|
||||
s1 = FactoryGirl.create(:supplier_enterprise)
|
||||
s2 = FactoryGirl.create(:supplier_enterprise)
|
||||
t1 = FactoryGirl.create(:taxon)
|
||||
t2 = FactoryGirl.create(:taxon)
|
||||
p = FactoryGirl.create(:product, supplier: s1, available_on: Date.today, variant_unit: 'volume', variant_unit_scale: 1, primary_taxon: t2, sku: "OLD SKU")
|
||||
p.price = 10.0
|
||||
p.on_hand = 6;
|
||||
p.save!
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
@@ -306,21 +252,16 @@ feature %q{
|
||||
expect(page).to have_field "product_name", with: p.name
|
||||
expect(page).to have_select "producer_id", selected: s1.name
|
||||
expect(page).to have_field "available_on", with: p.available_on.strftime("%F %T")
|
||||
expect(page).to have_field "price", with: "10.0"
|
||||
expect(page).to have_selector "div#s2id_p#{p.id}_category_id a.select2-choice"
|
||||
expect(page).to have_select2 "p#{p.id}_category_id", selected: t2.name
|
||||
expect(page).to have_select "variant_unit_with_scale", selected: "Volume (L)"
|
||||
expect(page).to have_field "on_hand", with: "6"
|
||||
expect(page).to have_checked_field "inherits_properties"
|
||||
expect(page).to have_field "product_sku", with: p.sku
|
||||
|
||||
fill_in "product_name", with: "Big Bag Of Potatoes"
|
||||
select s2.name, :from => 'producer_id'
|
||||
fill_in "available_on", with: (3.days.ago.beginning_of_day).strftime("%F %T")
|
||||
fill_in "price", with: "20"
|
||||
select "Weight (kg)", from: "variant_unit_with_scale"
|
||||
select2_select t1.name, from: "p#{p.id}_category_id"
|
||||
fill_in "on_hand", with: "18"
|
||||
fill_in "display_as", with: "Big Bag"
|
||||
uncheck "inherits_properties"
|
||||
fill_in "product_sku", with: "NEW SKU"
|
||||
end
|
||||
@@ -334,9 +275,6 @@ feature %q{
|
||||
expect(p.variant_unit).to eq "weight"
|
||||
expect(p.variant_unit_scale).to eq 1000 # Kg
|
||||
expect(p.available_on).to eq 3.days.ago.beginning_of_day
|
||||
expect(p.master.display_as).to eq "Big Bag"
|
||||
expect(p.price).to eq 20.0
|
||||
expect(p.on_hand).to eq 18
|
||||
expect(p.primary_taxon).to eq t1
|
||||
expect(p.inherits_properties).to be false
|
||||
expect(p.sku).to eq "NEW SKU"
|
||||
@@ -363,74 +301,12 @@ feature %q{
|
||||
expect(p.variant_unit_name).to eq "loaf"
|
||||
end
|
||||
|
||||
scenario "setting a variant unit on a product that has none" do
|
||||
p = FactoryGirl.create(:product, variant_unit: nil, variant_unit_scale: nil)
|
||||
v = FactoryGirl.create(:variant, product: p, unit_value: nil, unit_description: nil)
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_select "variant_unit_with_scale", selected: ''
|
||||
|
||||
select "Weight (kg)", from: "variant_unit_with_scale"
|
||||
first("a.view-variants").trigger('click')
|
||||
fill_in "variant_unit_value_with_description", with: '123 abc'
|
||||
|
||||
first(:button, 'Save Changes').click
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
|
||||
p.reload
|
||||
expect(p.variant_unit).to eq "weight"
|
||||
expect(p.variant_unit_scale).to eq 1000 # Kg
|
||||
v.reload
|
||||
expect(v.unit_value).to eq 123000 # 123 kg in g
|
||||
expect(v.unit_description).to eq "abc"
|
||||
end
|
||||
|
||||
describe "setting the master unit value for a product without variants" do
|
||||
it "sets the master unit value" do
|
||||
p = FactoryGirl.create(:product, variant_unit: nil, variant_unit_scale: nil)
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_select "variant_unit_with_scale", selected: ''
|
||||
expect(page).to have_no_field "master_unit_value_with_description", visible: true
|
||||
|
||||
select "Weight (kg)", from: "variant_unit_with_scale"
|
||||
fill_in "master_unit_value_with_description", with: '123 abc'
|
||||
|
||||
first(:button, 'Save Changes').click
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
|
||||
p.reload
|
||||
expect(p.variant_unit).to eq 'weight'
|
||||
expect(p.variant_unit_scale).to eq 1000
|
||||
expect(p.master.unit_value).to eq 123000
|
||||
expect(p.master.unit_description).to eq 'abc'
|
||||
end
|
||||
|
||||
it "does not show the field when the product has variants" do
|
||||
p = FactoryGirl.create(:product, variant_unit: nil, variant_unit_scale: nil)
|
||||
v = FactoryGirl.create(:variant, product: p, unit_value: nil, unit_description: nil)
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
select "Weight (kg)", from: "variant_unit_with_scale"
|
||||
expect(page).to have_no_field "master_unit_value_with_description", visible: true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
scenario "updating a product with variants" do
|
||||
s1 = FactoryGirl.create(:supplier_enterprise)
|
||||
s2 = FactoryGirl.create(:supplier_enterprise)
|
||||
p = FactoryGirl.create(:product, supplier: s1, available_on: Date.today, variant_unit: 'volume', variant_unit_scale: 0.001)
|
||||
v = FactoryGirl.create(:variant, product: p, price: 3.0, on_hand: 9, unit_value: 0.25, unit_description: '(bottle)')
|
||||
p = FactoryGirl.create(:product, supplier: s1, available_on: Date.today, variant_unit: 'volume', variant_unit_scale: 0.001,
|
||||
price: 3.0, on_hand: 9, unit_value: 0.25, unit_description: '(bottle)' )
|
||||
v = p.variants.first
|
||||
|
||||
login_to_admin_section
|
||||
|
||||
@@ -441,7 +317,7 @@ feature %q{
|
||||
expect(page).to have_field "variant_price", with: "3.0"
|
||||
expect(page).to have_field "variant_unit_value_with_description", with: "250 (bottle)"
|
||||
expect(page).to have_field "variant_on_hand", with: "9"
|
||||
expect(page).to have_selector "span[name='on_hand']", text: "9"
|
||||
expect(page).to have_selector "span[name='on_hand']", "9"
|
||||
|
||||
select "Volume (L)", from: "variant_unit_with_scale"
|
||||
fill_in "variant_price", with: "4.0"
|
||||
@@ -472,7 +348,9 @@ feature %q{
|
||||
|
||||
expect(page).to have_field "variant_price", with: "3.0"
|
||||
|
||||
fill_in "variant_price", with: "10.0"
|
||||
within "#v_#{v.id}" do
|
||||
fill_in "variant_price", with: "10.0"
|
||||
end
|
||||
|
||||
first(:button, 'Save Changes').click
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
@@ -561,40 +439,39 @@ feature %q{
|
||||
|
||||
describe "using action buttons" do
|
||||
describe "using delete buttons" do
|
||||
it "shows a delete button for products, which deletes the appropriate product when clicked" do
|
||||
p1 = FactoryGirl.create(:product)
|
||||
p2 = FactoryGirl.create(:product)
|
||||
p3 = FactoryGirl.create(:product)
|
||||
login_to_admin_section
|
||||
let!(:p1) { FactoryGirl.create(:product) }
|
||||
let!(:p2) { FactoryGirl.create(:product) }
|
||||
let!(:v1) { p1.variants.first }
|
||||
let!(:v2) { p2.variants.first }
|
||||
let!(:v3) { FactoryGirl.create(:variant, product: p2 ) }
|
||||
|
||||
|
||||
before do
|
||||
quick_login_as_admin
|
||||
visit '/admin/products/bulk_edit'
|
||||
end
|
||||
|
||||
expect(page).to have_selector "a.delete-product", :count => 3
|
||||
it "shows a delete button for products, which deletes the appropriate product when clicked" do
|
||||
expect(page).to have_selector "a.delete-product", :count => 2
|
||||
|
||||
within "tr#p_#{p1.id}" do
|
||||
first("a.delete-product").click
|
||||
end
|
||||
|
||||
expect(page).to have_selector "a.delete-product", :count => 2
|
||||
expect(page).to have_selector "a.delete-product", :count => 1
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_selector "a.delete-product", :count => 2
|
||||
expect(page).to have_selector "a.delete-product", :count => 1
|
||||
end
|
||||
|
||||
it "shows a delete button for variants, which deletes the appropriate variant when clicked" do
|
||||
v1 = FactoryGirl.create(:variant)
|
||||
v2 = FactoryGirl.create(:variant)
|
||||
v3 = FactoryGirl.create(:variant)
|
||||
login_to_admin_section
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
expect(page).to have_selector "a.view-variants"
|
||||
all("a.view-variants").each { |e| e.trigger('click') }
|
||||
|
||||
expect(page).to have_selector "a.delete-variant", :count => 3
|
||||
|
||||
within "tr#v_#{v1.id}" do
|
||||
within "tr#v_#{v3.id}" do
|
||||
first("a.delete-variant").click
|
||||
end
|
||||
|
||||
@@ -609,15 +486,18 @@ feature %q{
|
||||
end
|
||||
|
||||
describe "using edit buttons" do
|
||||
it "shows an edit button for products, which takes the user to the standard edit page for that product" do
|
||||
p1 = FactoryGirl.create(:product)
|
||||
p2 = FactoryGirl.create(:product)
|
||||
p3 = FactoryGirl.create(:product)
|
||||
login_to_admin_section
|
||||
let!(:p1) { FactoryGirl.create(:product) }
|
||||
let!(:p2) { FactoryGirl.create(:product) }
|
||||
let!(:v1) { p1.variants.first }
|
||||
let!(:v2) { p2.variants.first }
|
||||
|
||||
before do
|
||||
quick_login_as_admin
|
||||
visit '/admin/products/bulk_edit'
|
||||
end
|
||||
|
||||
expect(page).to have_selector "a.edit-product", :count => 3
|
||||
it "shows an edit button for products, which takes the user to the standard edit page for that product" do
|
||||
expect(page).to have_selector "a.edit-product", :count => 2
|
||||
|
||||
within "tr#p_#{p1.id}" do
|
||||
first("a.edit-product").click
|
||||
@@ -627,16 +507,10 @@ feature %q{
|
||||
end
|
||||
|
||||
it "shows an edit button for variants, which takes the user to the standard edit page for that variant" do
|
||||
v1 = FactoryGirl.create(:variant)
|
||||
v2 = FactoryGirl.create(:variant)
|
||||
v3 = FactoryGirl.create(:variant)
|
||||
login_to_admin_section
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
expect(page).to have_selector "a.view-variants"
|
||||
all("a.view-variants").each { |e| e.trigger('click') }
|
||||
|
||||
expect(page).to have_selector "a.edit-variant", :count => 3
|
||||
expect(page).to have_selector "a.edit-variant", :count => 2
|
||||
|
||||
within "tr#v_#{v1.id}" do
|
||||
first("a.edit-variant").click
|
||||
@@ -796,6 +670,8 @@ feature %q{
|
||||
within 'fieldset#new_product' do
|
||||
fill_in 'product_name', with: 'Big Bag Of Apples'
|
||||
select supplier_permitted.name, from: 'product_supplier_id'
|
||||
select 'Weight (g)', from: 'product_variant_unit_with_scale'
|
||||
fill_in 'product_unit_value_with_description', with: '100'
|
||||
fill_in 'product_price', with: '10.00'
|
||||
select taxon.name, from: 'product_primary_taxon_id'
|
||||
end
|
||||
@@ -808,6 +684,7 @@ feature %q{
|
||||
|
||||
it "allows me to update a product" do
|
||||
p = product_supplied_permitted
|
||||
v = p.variants.first
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
@@ -817,30 +694,34 @@ feature %q{
|
||||
expect(page).to have_field "product_name", with: p.name
|
||||
expect(page).to have_select "producer_id", selected: supplier_permitted.name
|
||||
expect(page).to have_field "available_on", with: p.available_on.strftime("%F %T")
|
||||
expect(page).to have_field "price", with: "10.0"
|
||||
expect(page).to have_field "on_hand", with: "6"
|
||||
|
||||
fill_in "product_name", with: "Big Bag Of Potatoes"
|
||||
select supplier_managed2.name, :from => 'producer_id'
|
||||
fill_in "available_on", with: (3.days.ago.beginning_of_day).strftime("%F %T")
|
||||
fill_in "price", with: "20"
|
||||
select "Weight (kg)", from: "variant_unit_with_scale"
|
||||
fill_in "on_hand", with: "18"
|
||||
fill_in "display_as", with: "Big Bag"
|
||||
|
||||
find("a.view-variants").trigger('click')
|
||||
end
|
||||
|
||||
within "#v_#{v.id}" do
|
||||
fill_in "variant_price", with: "20"
|
||||
fill_in "variant_on_hand", with: "18"
|
||||
fill_in "variant_display_as", with: "Big Bag"
|
||||
end
|
||||
|
||||
first(:button, 'Save Changes').click
|
||||
expect(page.find("#status-message")).to have_content "Changes saved."
|
||||
|
||||
p.reload
|
||||
v.reload
|
||||
expect(p.name).to eq "Big Bag Of Potatoes"
|
||||
expect(p.supplier).to eq supplier_managed2
|
||||
expect(p.variant_unit).to eq "weight"
|
||||
expect(p.variant_unit_scale).to eq 1000 # Kg
|
||||
expect(p.available_on).to eq 3.days.ago.beginning_of_day
|
||||
expect(p.master.display_as).to eq "Big Bag"
|
||||
expect(p.price).to eq 20.0
|
||||
expect(p.on_hand).to eq 18
|
||||
expect(v.display_as).to eq "Big Bag"
|
||||
expect(v.price).to eq 20.0
|
||||
expect(v.on_hand).to eq 18
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,7 +50,7 @@ feature %q{
|
||||
eg.name.should == 'EGEGEG'
|
||||
eg.description.should == 'This is a description'
|
||||
eg.on_front_page.should be_true
|
||||
eg.enterprises.sort.should == [e1, e2].sort
|
||||
eg.enterprises.should match_array [e1, e2]
|
||||
end
|
||||
|
||||
scenario "editing an enterprise group" do
|
||||
|
||||
@@ -50,7 +50,7 @@ feature %q{
|
||||
page.should have_relationship e1, e2, ['to add to order cycle', 'to override variant details', 'to edit profile']
|
||||
er = EnterpriseRelationship.where(parent_id: e1, child_id: e2).first
|
||||
er.should be_present
|
||||
er.permissions.map(&:name).sort.should == ['add_to_order_cycle', 'edit_profile', 'create_variant_overrides'].sort
|
||||
er.permissions.map(&:name).should match_array ['add_to_order_cycle', 'edit_profile', 'create_variant_overrides']
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ feature %q{
|
||||
page.should have_selector 'td.distributors', text: 'My distributor'
|
||||
|
||||
# And my coordinator fees should have been configured
|
||||
OrderCycle.last.coordinator_fee_ids.sort.should == [coordinator_fee1.id, coordinator_fee2.id].sort
|
||||
OrderCycle.last.coordinator_fee_ids.should match_array [coordinator_fee1.id, coordinator_fee2.id]
|
||||
|
||||
# And my supplier fees should have been configured
|
||||
OrderCycle.last.exchanges.incoming.last.enterprise_fee_ids.should == [supplier_fee2.id]
|
||||
@@ -364,7 +364,7 @@ feature %q{
|
||||
|
||||
# And it should have some variants selected
|
||||
selected_initial_variants = initial_variants.take initial_variants.size - 1
|
||||
OrderCycle.last.variants.map(&:id).sort.should == (selected_initial_variants.map(&:id) + [v1.id, v2.id]).sort
|
||||
OrderCycle.last.variants.map(&:id).should match_array (selected_initial_variants.map(&:id) + [v1.id, v2.id])
|
||||
|
||||
# And the collection details should have been updated
|
||||
OrderCycle.last.exchanges.where(pickup_time: 'New time 0', pickup_instructions: 'New instructions 0').should be_present
|
||||
@@ -487,7 +487,9 @@ feature %q{
|
||||
let!(:shipping_method) { create(:shipping_method, distributors: [distributor_managed, distributor_unmanaged, distributor_permitted]) }
|
||||
let!(:payment_method) { create(:payment_method, distributors: [distributor_managed, distributor_unmanaged, distributor_permitted]) }
|
||||
let!(:product_managed) { create(:product, supplier: supplier_managed) }
|
||||
let!(:variant_managed) { product_managed.variants.first }
|
||||
let!(:product_permitted) { create(:product, supplier: supplier_permitted) }
|
||||
let!(:variant_permitted) { product_permitted.variants.first }
|
||||
|
||||
before do
|
||||
# Relationships required for interface to work
|
||||
@@ -533,8 +535,6 @@ feature %q{
|
||||
click_link "Order Cycles"
|
||||
click_link 'New Order Cycle'
|
||||
|
||||
# We go straight through to the new form, because only one coordinator is available
|
||||
|
||||
fill_in 'order_cycle_name', with: 'My order cycle'
|
||||
fill_in 'order_cycle_orders_open_at', with: '2040-11-06 06:00:00'
|
||||
fill_in 'order_cycle_orders_close_at', with: '2040-11-13 17:00:00'
|
||||
@@ -544,8 +544,8 @@ feature %q{
|
||||
select 'Permitted supplier', from: 'new_supplier_id'
|
||||
click_button 'Add supplier'
|
||||
|
||||
select_incoming_variant supplier_managed, 0, product_managed.master
|
||||
select_incoming_variant supplier_permitted, 1, product_permitted.master
|
||||
select_incoming_variant supplier_managed, 0, variant_managed
|
||||
select_incoming_variant supplier_permitted, 1, variant_permitted
|
||||
|
||||
click_button 'Add coordinator fee'
|
||||
select 'Managed distributor fee', from: 'order_cycle_coordinator_fee_0_id'
|
||||
@@ -568,9 +568,9 @@ feature %q{
|
||||
|
||||
flash_message.should == "Your order cycle has been created."
|
||||
order_cycle = OrderCycle.find_by_name('My order cycle')
|
||||
order_cycle.suppliers.sort.should == [supplier_managed, supplier_permitted].sort
|
||||
order_cycle.suppliers.should match_array [supplier_managed, supplier_permitted]
|
||||
order_cycle.coordinator.should == distributor_managed
|
||||
order_cycle.distributors.sort.should == [distributor_managed, distributor_permitted].sort
|
||||
order_cycle.distributors.should match_array [distributor_managed, distributor_permitted]
|
||||
end
|
||||
|
||||
scenario "editing an order cycle we can see (and for now, edit) all exchanges in the order cycle" do
|
||||
@@ -592,9 +592,9 @@ feature %q{
|
||||
page.should have_content "Your order cycle has been updated."
|
||||
|
||||
oc.reload
|
||||
oc.suppliers.sort.should == [supplier_managed, supplier_permitted, supplier_unmanaged].sort
|
||||
oc.suppliers.should match_array [supplier_managed, supplier_permitted, supplier_unmanaged]
|
||||
oc.coordinator.should == distributor_managed
|
||||
oc.distributors.sort.should == [distributor_managed, distributor_permitted, distributor_unmanaged].sort
|
||||
oc.distributors.should match_array [distributor_managed, distributor_permitted, distributor_unmanaged]
|
||||
end
|
||||
|
||||
scenario "editing an order cycle" do
|
||||
@@ -683,9 +683,9 @@ feature %q{
|
||||
page.should have_content "Your order cycle has been updated."
|
||||
|
||||
oc.reload
|
||||
oc.suppliers.sort.should == [supplier_managed, supplier_permitted, supplier_unmanaged].sort
|
||||
oc.suppliers.should match_array [supplier_managed, supplier_permitted, supplier_unmanaged]
|
||||
oc.coordinator.should == distributor_managed
|
||||
oc.distributors.sort.should == [distributor_managed, distributor_permitted, distributor_unmanaged].sort
|
||||
oc.distributors.should match_array [distributor_managed, distributor_permitted, distributor_unmanaged]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -736,9 +736,9 @@ feature %q{
|
||||
page.should have_content "Your order cycle has been updated."
|
||||
|
||||
oc.reload
|
||||
oc.suppliers.sort.should == [supplier_managed, supplier_permitted, supplier_unmanaged].sort
|
||||
oc.suppliers.should match_array [supplier_managed, supplier_permitted, supplier_unmanaged]
|
||||
oc.coordinator.should == distributor_managed
|
||||
oc.distributors.sort.should == [my_distributor, distributor_managed, distributor_permitted, distributor_unmanaged].sort
|
||||
oc.distributors.should match_array [my_distributor, distributor_managed, distributor_permitted, distributor_unmanaged]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -750,7 +750,9 @@ feature %q{
|
||||
let!(:p1) { create(:simple_product, supplier: enterprise) }
|
||||
let!(:p2) { create(:simple_product, supplier: enterprise) }
|
||||
let!(:p3) { create(:simple_product, supplier: enterprise) }
|
||||
let!(:v) { create(:variant, product: p3) }
|
||||
let!(:v1) { p1.variants.first }
|
||||
let!(:v2) { p2.variants.first }
|
||||
let!(:v3) { p3.variants.first }
|
||||
let!(:fee) { create(:enterprise_fee, enterprise: enterprise, name: 'Coord fee') }
|
||||
|
||||
before do
|
||||
@@ -779,12 +781,12 @@ feature %q{
|
||||
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions'
|
||||
|
||||
# Then my products / variants should already be selected
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p1.master.id}"
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v.id}"
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v1.id}"
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v2.id}"
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v3.id}"
|
||||
|
||||
# When I unselect a product
|
||||
uncheck "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
|
||||
uncheck "order_cycle_incoming_exchange_0_variants_#{v2.id}"
|
||||
|
||||
# And I add a fee and save
|
||||
click_button 'Add coordinator fee'
|
||||
@@ -819,7 +821,7 @@ feature %q{
|
||||
scenario "editing an order cycle" do
|
||||
# Given an order cycle with pickup time and instructions
|
||||
fee = create(:enterprise_fee, name: 'my fee', enterprise: enterprise)
|
||||
oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee])
|
||||
oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [v1], coordinator_fees: [fee])
|
||||
ex = oc.exchanges.outgoing.first
|
||||
ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions'
|
||||
|
||||
@@ -837,9 +839,9 @@ feature %q{
|
||||
page.should have_field 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions'
|
||||
|
||||
# And I should see the products
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{p1.master.id}"
|
||||
page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
|
||||
page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{v.id}"
|
||||
page.should have_checked_field "order_cycle_incoming_exchange_0_variants_#{v1.id}"
|
||||
page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{v2.id}"
|
||||
page.should have_unchecked_field "order_cycle_incoming_exchange_0_variants_#{v3.id}"
|
||||
|
||||
# And I should see the coordinator fees
|
||||
page.should have_select 'order_cycle_coordinator_fee_0_id', selected: 'my fee'
|
||||
@@ -849,7 +851,7 @@ feature %q{
|
||||
# Given an order cycle with pickup time and instructions
|
||||
fee1 = create(:enterprise_fee, name: 'my fee', enterprise: enterprise)
|
||||
fee2 = create(:enterprise_fee, name: 'that fee', enterprise: enterprise)
|
||||
oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [p1.master], coordinator_fees: [fee1])
|
||||
oc = create(:simple_order_cycle, suppliers: [enterprise], coordinator: enterprise, distributors: [enterprise], variants: [v1], coordinator_fees: [fee1])
|
||||
ex = oc.exchanges.outgoing.first
|
||||
ex.update_attributes! pickup_time: 'pickup time', pickup_instructions: 'pickup instructions'
|
||||
|
||||
@@ -866,10 +868,10 @@ feature %q{
|
||||
fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'zzy'
|
||||
|
||||
# And I make some product selections
|
||||
uncheck "order_cycle_incoming_exchange_0_variants_#{p1.master.id}"
|
||||
check "order_cycle_incoming_exchange_0_variants_#{p2.master.id}"
|
||||
check "order_cycle_incoming_exchange_0_variants_#{v.id}"
|
||||
uncheck "order_cycle_incoming_exchange_0_variants_#{v.id}"
|
||||
uncheck "order_cycle_incoming_exchange_0_variants_#{v1.id}"
|
||||
check "order_cycle_incoming_exchange_0_variants_#{v2.id}"
|
||||
check "order_cycle_incoming_exchange_0_variants_#{v3.id}"
|
||||
uncheck "order_cycle_incoming_exchange_0_variants_#{v3.id}"
|
||||
|
||||
# And I select some fees and update
|
||||
click_link 'order_cycle_coordinator_fee_0_remove'
|
||||
@@ -887,8 +889,8 @@ feature %q{
|
||||
|
||||
# And it should have a variant selected
|
||||
oc = OrderCycle.last
|
||||
oc.exchanges.incoming.first.variants.should == [p2.master]
|
||||
oc.exchanges.outgoing.first.variants.should == [p2.master]
|
||||
oc.exchanges.incoming.first.variants.should == [v2]
|
||||
oc.exchanges.outgoing.first.variants.should == [v2]
|
||||
|
||||
# And it should have the fee
|
||||
oc.coordinator_fees.should == [fee2]
|
||||
|
||||
@@ -11,7 +11,7 @@ feature %q{
|
||||
@user = create(:user)
|
||||
@product = create(:simple_product)
|
||||
@distributor = create(:distributor_enterprise)
|
||||
@order_cycle = create(:simple_order_cycle, distributors: [@distributor], variants: [@product.master])
|
||||
@order_cycle = create(:simple_order_cycle, distributors: [@distributor], variants: [@product.variants.first])
|
||||
|
||||
@order = create(:order_with_totals_and_distribution, user: @user, distributor: @distributor, order_cycle: @order_cycle, state: 'complete', payment_state: 'balance_due')
|
||||
|
||||
|
||||
@@ -68,10 +68,10 @@ feature %q{
|
||||
click_button 'Update'
|
||||
|
||||
product.reload
|
||||
product.distributors.sort.should == [@distributors[0], @distributors[2]].sort
|
||||
product.distributors.should match_array [@distributors[0], @distributors[2]]
|
||||
|
||||
|
||||
product.product_distributions.map { |pd| pd.enterprise_fee }.sort.should == [@enterprise_fees[0], @enterprise_fees[2]].sort
|
||||
product.product_distributions.map { |pd| pd.enterprise_fee }.should match_array [@enterprise_fees[0], @enterprise_fees[2]]
|
||||
end
|
||||
|
||||
scenario "making a product into a group buy product" do
|
||||
@@ -117,9 +117,8 @@ feature %q{
|
||||
end
|
||||
end
|
||||
|
||||
scenario "creating a new product" do
|
||||
scenario "creating a new product", js: true do
|
||||
Spree::Config.products_require_tax_category = false
|
||||
|
||||
click_link 'Products'
|
||||
click_link 'New Product'
|
||||
|
||||
@@ -128,6 +127,8 @@ feature %q{
|
||||
|
||||
page.should have_selector('#product_supplier_id')
|
||||
select 'Another Supplier', :from => 'product_supplier_id'
|
||||
select 'Weight (g)', from: 'product_variant_unit_with_scale'
|
||||
fill_in 'product_unit_value_with_description', with: '500'
|
||||
select taxon.name, from: "product_primary_taxon_id"
|
||||
select 'None', from: "product_tax_category_id"
|
||||
|
||||
|
||||
@@ -224,14 +224,16 @@ feature %q{
|
||||
|
||||
describe "products and inventory report" do
|
||||
it "shows products and inventory report" do
|
||||
product_1 = create(:simple_product, name: "Product Name", variant_unit: nil)
|
||||
variant_1 = create(:variant, product: product_1, price: 100.0)
|
||||
variant_2 = create(:variant, product: product_1, price: 80.0)
|
||||
product_2 = create(:simple_product, name: "Product 2", price: 99.0, variant_unit: nil)
|
||||
variant_1.update_column(:count_on_hand, 10)
|
||||
variant_2.update_column(:count_on_hand, 20)
|
||||
product_2.master.update_column(:count_on_hand, 9)
|
||||
variant_1.option_values = [create(:option_value, :presentation => "Test")]
|
||||
product1 = create(:simple_product, name: "Product Name", price: 100)
|
||||
variant1 = product1.variants.first
|
||||
variant2 = create(:variant, product: product1, price: 80.0)
|
||||
product2 = create(:simple_product, name: "Product 2", price: 99.0, variant_unit: 'weight', variant_unit_scale: 1, unit_value: '100')
|
||||
variant3 = product2.variants.first
|
||||
variant1.update_column(:count_on_hand, 10)
|
||||
variant2.update_column(:count_on_hand, 20)
|
||||
variant3.update_column(:count_on_hand, 9)
|
||||
variant1.option_values = [create(:option_value, :presentation => "Test")]
|
||||
variant2.option_values = [create(:option_value, :presentation => "Something")]
|
||||
|
||||
login_to_admin_section
|
||||
click_link 'Reports'
|
||||
@@ -245,10 +247,10 @@ feature %q{
|
||||
table = rows.map { |r| r.all("th,td").map { |c| c.text.strip } }
|
||||
|
||||
table.sort.should == [
|
||||
["Supplier", "Producer Suburb", "Product", "Product Properties", "Taxons", "Variant Value", "Price", "Group Buy Unit Quantity", "Amount"],
|
||||
[product_1.supplier.name, product_1.supplier.address.city, "Product Name", product_1.properties.join(", "), product_1.primary_taxon.name, "Test", "100.0", product_1.group_buy_unit_size.to_s, ""],
|
||||
[product_1.supplier.name, product_1.supplier.address.city, "Product Name", product_1.properties.join(", "), product_1.primary_taxon.name, "S", "80.0", product_1.group_buy_unit_size.to_s, ""],
|
||||
[product_2.supplier.name, product_1.supplier.address.city, "Product 2", product_1.properties.join(", "), product_2.primary_taxon.name, "", "99.0", product_1.group_buy_unit_size.to_s, ""]
|
||||
["Supplier", "Producer Suburb", "Product", "Product Properties", "Taxons", "Variant Value", "Price", "Group Buy Unit Quantity", "Amount"],
|
||||
[product1.supplier.name, product1.supplier.address.city, "Product Name", product1.properties.join(", "), product1.primary_taxon.name, "Test", "100.0", product1.group_buy_unit_size.to_s, ""],
|
||||
[product1.supplier.name, product1.supplier.address.city, "Product Name", product1.properties.join(", "), product1.primary_taxon.name, "Something", "80.0", product1.group_buy_unit_size.to_s, ""],
|
||||
[product2.supplier.name, product1.supplier.address.city, "Product 2", product1.properties.join(", "), product2.primary_taxon.name, "100g", "99.0", product1.group_buy_unit_size.to_s, ""]
|
||||
].sort
|
||||
end
|
||||
end
|
||||
|
||||
@@ -36,7 +36,7 @@ feature 'shipping methods' do
|
||||
|
||||
sm = Spree::ShippingMethod.last
|
||||
sm.name.should == 'Carrier Pidgeon'
|
||||
sm.distributors.sort.should == [d1, d2].sort
|
||||
sm.distributors.should match_array [d1, d2]
|
||||
end
|
||||
|
||||
it "at checkout, user can only see shipping methods for their current distributor (checkout spec)"
|
||||
|
||||
@@ -25,10 +25,11 @@ feature %q{
|
||||
end
|
||||
|
||||
|
||||
scenario "editing unit value and description for a variant" do
|
||||
scenario "editing unit value and description for a variant", js:true do
|
||||
# Given a product with unit-related option types, with a variant
|
||||
p = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
v = create(:variant, product: p, unit_value: 1, unit_description: 'foo')
|
||||
v = p.variants.first
|
||||
v.update_attributes( unit_value: 1, unit_description: 'foo' )
|
||||
|
||||
# And the product has option types for the unit-related and non-unit-related option values
|
||||
p.option_types << v.option_values.first.option_type
|
||||
@@ -39,7 +40,7 @@ feature %q{
|
||||
page.find('table.index .icon-edit').click
|
||||
|
||||
# Then I should not see a traditional option value field for the unit-related option value
|
||||
page.all("div[data-hook='presentation'] input").count.should == 1
|
||||
expect(page).to_not have_selector "div[data-hook='presentation'] input"
|
||||
|
||||
# And I should see unit value and description fields for the unit-related option value
|
||||
page.should have_field "variant_unit_value", with: "1"
|
||||
@@ -57,24 +58,6 @@ feature %q{
|
||||
v.unit_description.should == 'bar'
|
||||
end
|
||||
|
||||
it "does not show unit value or description fields when the product does not have a unit-related option type" do
|
||||
# Given a product without unit-related option types, with a variant
|
||||
p = create(:simple_product, variant_unit: nil, variant_unit_scale: nil)
|
||||
v = create(:variant, product: p, unit_value: nil, unit_description: nil)
|
||||
|
||||
# And the product has option types for the variant's option values
|
||||
p.option_types << v.option_values.first.option_type
|
||||
|
||||
# When I view the variant
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path p
|
||||
page.find('table.index .icon-edit').click
|
||||
|
||||
# Then I should not see unit value and description fields
|
||||
page.should_not have_field "variant_unit_value"
|
||||
page.should_not have_field "variant_unit_description"
|
||||
end
|
||||
|
||||
it "soft-deletes variants", js: true do
|
||||
p = create(:simple_product)
|
||||
v = create(:variant, product: p)
|
||||
@@ -82,7 +65,9 @@ feature %q{
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path p
|
||||
|
||||
page.find('a.delete-resource').click
|
||||
within "tr#spree_variant_#{v.id}" do
|
||||
page.find('a.delete-resource').click
|
||||
end
|
||||
page.should_not have_content v.options_text
|
||||
|
||||
v.reload
|
||||
|
||||
@@ -3,6 +3,11 @@ require 'spec_helper'
|
||||
feature "Authentication", js: true do
|
||||
include UIComponentHelper
|
||||
|
||||
# Attempt to address intermittent failures in these specs
|
||||
around do |example|
|
||||
Capybara.using_wait_time(120) { example.run }
|
||||
end
|
||||
|
||||
describe "login" do
|
||||
let(:user) { create(:user, password: "password", password_confirmation: "password") }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
|
||||
let(:oc1) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) }
|
||||
let(:oc2) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 3.days.from_now) }
|
||||
let(:product) { create(:simple_product, supplier: supplier) }
|
||||
let(:variant) { product.variants.first }
|
||||
let(:order) { create(:order, distributor: distributor) }
|
||||
|
||||
before do
|
||||
@@ -33,7 +34,7 @@ feature "As a consumer I want to shop with a distributor", js: true do
|
||||
|
||||
it "shows the producers for a distributor" do
|
||||
exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
|
||||
exchange.variants << product.master
|
||||
exchange.variants << variant
|
||||
|
||||
visit shop_path
|
||||
find("#tab_producers a").click
|
||||
@@ -64,9 +65,9 @@ feature "As a consumer I want to shop with a distributor", js: true do
|
||||
end
|
||||
|
||||
it "shows products after selecting an order cycle" do
|
||||
product.master.update_attribute(:display_name, "kitten")
|
||||
product.master.update_attribute(:display_as, "rabbit")
|
||||
exchange1.variants << product.master ## add product to exchange
|
||||
variant.update_attribute(:display_name, "kitten")
|
||||
variant.update_attribute(:display_as, "rabbit")
|
||||
exchange1.variants << variant ## add product to exchange
|
||||
visit shop_path
|
||||
page.should_not have_content product.name
|
||||
Spree::Order.last.order_cycle.should == nil
|
||||
@@ -76,8 +77,8 @@ feature "As a consumer I want to shop with a distributor", js: true do
|
||||
page.should have_content "Next order closing in 2 days"
|
||||
Spree::Order.last.order_cycle.should == oc1
|
||||
page.should have_content product.name
|
||||
page.should have_content product.master.display_name
|
||||
page.should have_content product.master.display_as
|
||||
page.should have_content variant.display_name
|
||||
page.should have_content variant.display_as
|
||||
|
||||
open_product_modal product
|
||||
modal_should_be_open_for product
|
||||
@@ -92,17 +93,12 @@ feature "As a consumer I want to shop with a distributor", js: true do
|
||||
|
||||
before do
|
||||
exchange.update_attribute :pickup_time, "frogs"
|
||||
exchange.variants << product.master
|
||||
exchange.variants << variant
|
||||
exchange.variants << variant1
|
||||
exchange.variants << variant2
|
||||
order.order_cycle = oc1
|
||||
end
|
||||
|
||||
it "should not show quantity field for product with variants" do
|
||||
visit shop_path
|
||||
page.should_not have_selector("#variants_#{product.master.id}", visible: true)
|
||||
end
|
||||
|
||||
it "uses the adjusted price" do
|
||||
enterprise_fee1 = create(:enterprise_fee, amount: 20)
|
||||
enterprise_fee2 = create(:enterprise_fee, amount: 3)
|
||||
@@ -126,38 +122,9 @@ feature "As a consumer I want to shop with a distributor", js: true do
|
||||
describe "group buy products" do
|
||||
let(:exchange) { Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id) }
|
||||
let(:product) { create(:simple_product, group_buy: true, on_hand: 15) }
|
||||
let(:variant) { product.variants.first }
|
||||
let(:product2) { create(:simple_product, group_buy: false) }
|
||||
|
||||
describe "without variants" do
|
||||
before do
|
||||
add_product_to_order_cycle(exchange, product)
|
||||
set_order_cycle(order, oc1)
|
||||
visit shop_path
|
||||
end
|
||||
|
||||
it "should save group buy data to ze cart" do
|
||||
fill_in "variants[#{product.master.id}]", with: 5
|
||||
fill_in "variant_attributes[#{product.master.id}][max_quantity]", with: 9
|
||||
|
||||
wait_until { !cart_dirty }
|
||||
|
||||
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
|
||||
li.max_quantity.should == 9
|
||||
li.quantity.should == 5
|
||||
end
|
||||
|
||||
# TODO move to controller test
|
||||
pending "adding a product with a max quantity less than quantity results in max_quantity==quantity" do
|
||||
fill_in "variants[#{product.master.id}]", with: 5
|
||||
fill_in "variant_attributes[#{product.master.id}][max_quantity]", with: 1
|
||||
add_to_cart
|
||||
page.should have_content product.name
|
||||
li = Spree::Order.order(:created_at).last.line_items.order(:created_at).last
|
||||
li.max_quantity.should == 5
|
||||
li.quantity.should == 5
|
||||
end
|
||||
end
|
||||
|
||||
describe "with variants on the product" do
|
||||
let(:variant) { create(:variant, product: product, on_hand: 10 ) }
|
||||
before do
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
describe "unitsCtrl", ->
|
||||
ctrl = null
|
||||
scope = null
|
||||
product = null
|
||||
|
||||
beforeEach ->
|
||||
module('admin.products')
|
||||
inject ($rootScope, $controller, VariantUnitManager) ->
|
||||
scope = $rootScope
|
||||
ctrl = $controller 'unitsCtrl', {$scope: scope, VariantUnitManager: VariantUnitManager}
|
||||
|
||||
describe "interpretting variant_unit_with_scale", ->
|
||||
it "splits string with one underscore and stores the two parts", ->
|
||||
scope.product.variant_unit_with_scale = "weight_1000"
|
||||
scope.processVariantUnitWithScale()
|
||||
expect(scope.product.variant_unit).toEqual "weight"
|
||||
expect(scope.product.variant_unit_scale).toEqual 1000
|
||||
|
||||
it "interprets strings with no underscore as variant_unit", ->
|
||||
scope.product.variant_unit_with_scale = "items"
|
||||
scope.processVariantUnitWithScale()
|
||||
expect(scope.product.variant_unit).toEqual "items"
|
||||
expect(scope.product.variant_unit_scale).toEqual null
|
||||
|
||||
it "sets variant_unit and variant_unit_scale to null", ->
|
||||
scope.product.variant_unit_with_scale = null
|
||||
scope.processVariantUnitWithScale()
|
||||
expect(scope.product.variant_unit).toEqual null
|
||||
expect(scope.product.variant_unit_scale).toEqual null
|
||||
|
||||
describe "interpretting unit_value_with_description", ->
|
||||
beforeEach ->
|
||||
scope.product.master = {}
|
||||
|
||||
describe "when a variant_unit_scale is present", ->
|
||||
beforeEach ->
|
||||
scope.product.variant_unit_scale = 1
|
||||
|
||||
it "splits by whitespace in to unit_value and unit_description", ->
|
||||
scope.product.master.unit_value_with_description = "12 boxes"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 12
|
||||
expect(scope.product.master.unit_description).toEqual "boxes"
|
||||
|
||||
it "uses whole string as unit_value when only numerical characters are present", ->
|
||||
scope.product.master.unit_value_with_description = "12345"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 12345
|
||||
expect(scope.product.master.unit_description).toEqual ''
|
||||
|
||||
it "uses whole string as description when string does not start with a number", ->
|
||||
scope.product.master.unit_value_with_description = "boxes 12"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual null
|
||||
expect(scope.product.master.unit_description).toEqual "boxes 12"
|
||||
|
||||
it "does not require whitespace to split unit value and description", ->
|
||||
scope.product.master.unit_value_with_description = "12boxes"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 12
|
||||
expect(scope.product.master.unit_description).toEqual "boxes"
|
||||
|
||||
it "once a whitespace occurs, all subsequent numerical characters are counted as description", ->
|
||||
scope.product.master.unit_value_with_description = "123 54 boxes"
|
||||
scope.processUnitValueWithDescription()
|
||||
expect(scope.product.master.unit_value).toEqual 123
|
||||
expect(scope.product.master.unit_description).toEqual "54 boxes"
|
||||
@@ -779,22 +779,31 @@ describe "AdminProductEditCtrl", ->
|
||||
|
||||
|
||||
describe "deleting variants", ->
|
||||
describe "when the variant is the only one left on the product", ->
|
||||
it "alerts the user", ->
|
||||
spyOn(window, "alert")
|
||||
$scope.products = [
|
||||
{id: 1, variants: [{id: 1}]}
|
||||
]
|
||||
$scope.deleteVariant $scope.products[0], $scope.products[0].variants[0]
|
||||
expect(window.alert).toHaveBeenCalledWith "The last variant cannot be deleted!"
|
||||
|
||||
describe "when the variant has not been saved", ->
|
||||
it "removes the variant from products and dirtyProducts", ->
|
||||
spyOn(window, "confirm").andReturn true
|
||||
$scope.products = [
|
||||
{id: 1, variants: [{id: -1}]}
|
||||
{id: 1, variants: [{id: -1},{id: -2}]}
|
||||
]
|
||||
DirtyProducts.addVariantProperty 1, -1, "something", "something"
|
||||
DirtyProducts.addProductProperty 1, "something", "something"
|
||||
$scope.deleteVariant $scope.products[0], $scope.products[0].variants[0]
|
||||
expect($scope.products).toEqual([
|
||||
{id: 1, variants: []}
|
||||
{id: 1, variants: [{id: -2}]}
|
||||
])
|
||||
expect(DirtyProducts.all()).toEqual
|
||||
1: { id: 1, something: 'something'}
|
||||
|
||||
|
||||
|
||||
describe "when the variant has been saved", ->
|
||||
it "deletes variants with a http delete request to /api/products/product_permalink/variants/(variant_id)/soft_delete", ->
|
||||
spyOn(window, "confirm").andReturn true
|
||||
@@ -802,9 +811,14 @@ describe "AdminProductEditCtrl", ->
|
||||
{
|
||||
id: 9
|
||||
permalink_live: "apples"
|
||||
variants: [
|
||||
variants: [{
|
||||
id: 3
|
||||
price: 12
|
||||
},
|
||||
{
|
||||
id: 4
|
||||
price: 15
|
||||
}
|
||||
]
|
||||
}
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'spec_helper'
|
||||
module OpenFoodNetwork
|
||||
describe CustomersReport do
|
||||
context "as a site admin" do
|
||||
let(:user) do
|
||||
let(:user) do
|
||||
user = create(:user)
|
||||
user.spree_roles << Spree::Role.find_or_create_by_name!("admin")
|
||||
user
|
||||
@@ -44,14 +44,14 @@ module OpenFoodNetwork
|
||||
it "builds a table from a list of variants" do
|
||||
a = create(:address)
|
||||
d = create(:distributor_enterprise)
|
||||
o = create(:order, distributor: d, bill_address: a)
|
||||
o = create(:order, distributor: d, bill_address: a)
|
||||
o.shipping_method = create(:shipping_method)
|
||||
|
||||
subject.stub(:orders).and_return [o]
|
||||
subject.table.should == [[
|
||||
a.firstname, a.lastname,
|
||||
[a.address1, a.address2, a.city].join(" "),
|
||||
o.email, a.phone, d.name,
|
||||
a.firstname, a.lastname,
|
||||
[a.address1, a.address2, a.city].join(" "),
|
||||
o.email, a.phone, d.name,
|
||||
[d.address.address1, d.address.address2, d.address.city].join(" "),
|
||||
o.shipping_method.name
|
||||
]]
|
||||
@@ -74,7 +74,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
context "as an enterprise user" do
|
||||
let(:user) do
|
||||
let(:user) do
|
||||
user = create(:user)
|
||||
user.spree_roles = []
|
||||
user.save!
|
||||
@@ -131,7 +131,7 @@ module OpenFoodNetwork
|
||||
order2.line_items << create(:line_item, product: product2)
|
||||
|
||||
subject.stub(:params).and_return(supplier_id: supplier.id)
|
||||
subject.filter(orders).sort.should == [order1]
|
||||
subject.filter(orders).should == [order1]
|
||||
end
|
||||
|
||||
it "filters to a specific distributor" do
|
||||
@@ -141,7 +141,7 @@ module OpenFoodNetwork
|
||||
order2 = create(:order, distributor: d2)
|
||||
|
||||
subject.stub(:params).and_return(distributor_id: d1.id)
|
||||
subject.filter(orders).sort.should == [order1]
|
||||
subject.filter(orders).should == [order1]
|
||||
end
|
||||
|
||||
it "filters to a specific cycle" do
|
||||
@@ -151,7 +151,7 @@ module OpenFoodNetwork
|
||||
order2 = create(:order, order_cycle: oc2)
|
||||
|
||||
subject.stub(:params).and_return(order_cycle_id: oc1.id)
|
||||
subject.filter(orders).sort.should == [order1]
|
||||
subject.filter(orders).should == [order1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -300,8 +300,8 @@ module OpenFoodNetwork
|
||||
expect(exchange.sender).to eq sender
|
||||
expect(exchange.receiver).to eq receiver
|
||||
expect(exchange.incoming).to eq incoming
|
||||
expect(exchange.variants.sort).to eq [variant1, variant2].sort
|
||||
expect(exchange.enterprise_fees.sort).to eq [enterprise_fee1, enterprise_fee2].sort
|
||||
expect(exchange.variants).to match_array [variant1, variant2]
|
||||
expect(exchange.enterprise_fees).to match_array [enterprise_fee1, enterprise_fee2]
|
||||
|
||||
applicator.send(:touched_exchanges).should == [exchange]
|
||||
end
|
||||
@@ -345,8 +345,8 @@ module OpenFoodNetwork
|
||||
|
||||
it "updates the variants, enterprise fees and pickup information of the exchange" do
|
||||
exchange.reload
|
||||
expect(exchange.variants.sort).to eq [variant1, variant3].sort
|
||||
expect(exchange.enterprise_fees.sort).to eq [enterprise_fee2, enterprise_fee3]
|
||||
expect(exchange.variants).to match_array [variant1, variant3]
|
||||
expect(exchange.enterprise_fees).to match_array [enterprise_fee2, enterprise_fee3]
|
||||
expect(exchange.pickup_time).to eq 'New Pickup Time'
|
||||
expect(exchange.pickup_instructions).to eq 'New Pickup Instructions'
|
||||
expect(applicator.send(:touched_exchanges)).to eq [exchange]
|
||||
@@ -364,8 +364,8 @@ module OpenFoodNetwork
|
||||
|
||||
it "updates the variants, enterprise fees and pickup information of the exchange" do
|
||||
exchange.reload
|
||||
expect(exchange.variants.sort).to eq [variant1, variant3].sort
|
||||
expect(exchange.enterprise_fees.sort).to eq [enterprise_fee2, enterprise_fee3]
|
||||
expect(exchange.variants).to match_array [variant1, variant3]
|
||||
expect(exchange.enterprise_fees).to match_array [enterprise_fee2, enterprise_fee3]
|
||||
expect(exchange.pickup_time).to eq 'New Pickup Time'
|
||||
expect(exchange.pickup_instructions).to eq 'New Pickup Instructions'
|
||||
expect(applicator.send(:touched_exchanges)).to eq [exchange]
|
||||
@@ -383,8 +383,8 @@ module OpenFoodNetwork
|
||||
|
||||
it "updates the variants in the exchange, but not the fees or pickup information" do
|
||||
exchange.reload
|
||||
expect(exchange.variants.sort).to eq [variant1, variant3].sort
|
||||
expect(exchange.enterprise_fees.sort).to eq [enterprise_fee1, enterprise_fee2]
|
||||
expect(exchange.variants).to match_array [variant1, variant3]
|
||||
expect(exchange.enterprise_fees).to match_array [enterprise_fee1, enterprise_fee2]
|
||||
expect(exchange.pickup_time).to_not eq 'New Pickup Time'
|
||||
expect(exchange.pickup_instructions).to_not eq 'New Pickup Instructions'
|
||||
expect(applicator.send(:touched_exchanges)).to eq [exchange]
|
||||
|
||||
@@ -13,7 +13,7 @@ module OpenFoodNetwork
|
||||
before { allow(user).to receive(:admin?) { true } }
|
||||
|
||||
it "returns all enterprises" do
|
||||
expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to eq [e1, e2]
|
||||
expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to match_array [e1, e2]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,7 +24,7 @@ module OpenFoodNetwork
|
||||
it "returns only my managed enterprises any that have granting them P-OC" do
|
||||
expect(permissions).to receive(:managed_enterprises) { Enterprise.where(id: e1) }
|
||||
expect(permissions).to receive(:related_enterprises_granting).with(:some_permission) { Enterprise.where(id: e3) }
|
||||
expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to eq [e1, e3]
|
||||
expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to match_array [e1, e3]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -34,7 +34,7 @@ module OpenFoodNetwork
|
||||
before { allow(user).to receive(:admin?) { true } }
|
||||
|
||||
it "returns all enterprises" do
|
||||
expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to eq [e1, e2]
|
||||
expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to match_array [e1, e2]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,7 +47,7 @@ module OpenFoodNetwork
|
||||
expect(permissions).to receive(:managed_enterprises) { Enterprise.where(id: e1) }
|
||||
expect(permissions).to receive(:related_enterprises_granting).with(:some_permission) { Enterprise.where(id: e3) }
|
||||
expect(permissions).to receive(:related_enterprises_granted).with(:some_permission) { Enterprise.where(id: e4) }
|
||||
expect(permissions.send(:managed_and_related_enterprises_with, :some_permission)).to eq [e1, e3, e4]
|
||||
expect(permissions.send(:managed_and_related_enterprises_with, :some_permission)).to match_array [e1, e3, e4]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -98,7 +98,7 @@ module OpenFoodNetwork
|
||||
{1 => [e1.id], 2 => [e1.id, e2.id]}
|
||||
end
|
||||
|
||||
permissions.variant_override_producers.sort.should == [e1, e2].sort
|
||||
permissions.variant_override_producers.should match_array [e1, e2]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ require 'spec_helper'
|
||||
module OpenFoodNetwork
|
||||
describe ProductsAndInventoryReport do
|
||||
context "As a site admin" do
|
||||
let(:user) do
|
||||
let(:user) do
|
||||
user = create(:user)
|
||||
user.spree_roles << Spree::Role.find_or_create_by_name!("admin")
|
||||
user
|
||||
@@ -14,7 +14,7 @@ module OpenFoodNetwork
|
||||
|
||||
it "Should return headers" do
|
||||
subject.header.should == [
|
||||
"Supplier",
|
||||
"Supplier",
|
||||
"Producer Suburb",
|
||||
"Product",
|
||||
"Product Properties",
|
||||
@@ -63,7 +63,7 @@ module OpenFoodNetwork
|
||||
|
||||
context "As an enterprise user" do
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
let(:enterprise_user) do
|
||||
let(:enterprise_user) do
|
||||
user = create(:user)
|
||||
user.enterprise_roles.create(enterprise: supplier)
|
||||
user.spree_roles = []
|
||||
@@ -76,50 +76,43 @@ module OpenFoodNetwork
|
||||
describe "fetching child variants" do
|
||||
it "returns some variants" do
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
variant_1 = create(:variant, product: product1)
|
||||
variant_1 = product1.variants.first
|
||||
variant_2 = create(:variant, product: product1)
|
||||
|
||||
subject.child_variants.sort.should == [variant_1, variant_2].sort
|
||||
subject.child_variants.should match_array [variant_1, variant_2]
|
||||
end
|
||||
|
||||
it "should only return variants managed by the user" do
|
||||
product1 = create(:simple_product, supplier: create(:supplier_enterprise))
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
variant_1 = create(:variant, product: product1)
|
||||
variant_2 = create(:variant, product: product2)
|
||||
|
||||
variant_1 = product1.variants.first
|
||||
variant_2 = product2.variants.first
|
||||
|
||||
subject.child_variants.should == [variant_2]
|
||||
end
|
||||
end
|
||||
|
||||
describe "fetching master variants" do
|
||||
it "should only return variants managed by the user" do
|
||||
product1 = create(:simple_product, supplier: create(:supplier_enterprise))
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
|
||||
subject.master_variants.should == [product2.master]
|
||||
end
|
||||
|
||||
it "doesn't return master variants with siblings" do
|
||||
product = create(:simple_product, supplier: supplier)
|
||||
create(:variant, product: product)
|
||||
|
||||
subject.master_variants.should be_empty
|
||||
|
||||
subject.master_variants.should be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe "Filtering variants" do
|
||||
let(:variants) { Spree::Variant.scoped.joins(:product) }
|
||||
let(:variants) { Spree::Variant.scoped.joins(:product).where(is_master: false) }
|
||||
it "should return unfiltered variants sans-params" do
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
subject.filter(Spree::Variant.scoped).sort.should == [product1.master, product2.master].sort
|
||||
|
||||
subject.filter(Spree::Variant.scoped).should match_array [product1.master, product1.variants.first, product2.master, product2.variants.first]
|
||||
end
|
||||
it "should filter deleted products" do
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
product2.delete
|
||||
subject.filter(Spree::Variant.scoped).sort.should == [product1.master].sort
|
||||
subject.filter(Spree::Variant.scoped).should match_array [product1.master, product1.variants.first]
|
||||
end
|
||||
describe "based on report type" do
|
||||
it "returns only variants on hand" do
|
||||
@@ -127,7 +120,7 @@ module OpenFoodNetwork
|
||||
product2 = create(:simple_product, supplier: supplier, on_hand: 0)
|
||||
|
||||
subject.stub(:params).and_return(report_type: 'inventory')
|
||||
subject.filter(variants).should == [product1.master]
|
||||
subject.filter(variants).should == [product1.variants.first]
|
||||
end
|
||||
end
|
||||
it "filters to a specific supplier" do
|
||||
@@ -136,7 +129,7 @@ module OpenFoodNetwork
|
||||
product2 = create(:simple_product, supplier: supplier2)
|
||||
|
||||
subject.stub(:params).and_return(supplier_id: supplier.id)
|
||||
subject.filter(variants).should == [product1.master]
|
||||
subject.filter(variants).should == [product1.variants.first]
|
||||
end
|
||||
it "filters to a specific distributor" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
@@ -144,23 +137,23 @@ module OpenFoodNetwork
|
||||
product2 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
|
||||
subject.stub(:params).and_return(distributor_id: distributor.id)
|
||||
subject.filter(variants).should == [product2.master]
|
||||
subject.filter(variants).should == [product2.variants.first]
|
||||
end
|
||||
it "filters to a specific order cycle" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
product1 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product2 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.master])
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.variants.first])
|
||||
|
||||
subject.stub(:params).and_return(order_cycle_id: order_cycle.id)
|
||||
subject.filter(variants).should == [product1.master]
|
||||
subject.filter(variants).should == [product1.variants.first]
|
||||
end
|
||||
|
||||
it "should do all the filters at once" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
product1 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
product2 = create(:simple_product, supplier: supplier, distributors: [distributor])
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.master])
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.variants.first])
|
||||
|
||||
subject.stub(:params).and_return(
|
||||
order_cycle_id: order_cycle.id,
|
||||
|
||||
@@ -43,7 +43,7 @@ describe EnterpriseFee do
|
||||
ef3 = create(:enterprise_fee, calculator: Spree::Calculator::PerItem.new)
|
||||
ef4 = create(:enterprise_fee, calculator: Spree::Calculator::PriceSack.new)
|
||||
|
||||
EnterpriseFee.per_item.sort.should == [ef1, ef2, ef3, ef4].sort
|
||||
EnterpriseFee.per_item.should match_array [ef1, ef2, ef3, ef4]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,7 +52,7 @@ describe EnterpriseFee do
|
||||
ef1 = create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new)
|
||||
ef2 = create(:enterprise_fee, calculator: Spree::Calculator::FlexiRate.new)
|
||||
|
||||
EnterpriseFee.per_order.sort.should == [ef1, ef2].sort
|
||||
EnterpriseFee.per_order.should match_array [ef1, ef2]
|
||||
end
|
||||
|
||||
it "does not return fees with any other calculator" do
|
||||
|
||||
@@ -2,11 +2,32 @@ require 'spec_helper'
|
||||
|
||||
describe EnterpriseGroup do
|
||||
describe "validations" do
|
||||
it "pass with name, description and address" do
|
||||
e = EnterpriseGroup.new
|
||||
e.name = 'Test Group'
|
||||
e.description = 'A valid test group.'
|
||||
e.address = build(:address)
|
||||
e.should be_valid
|
||||
end
|
||||
|
||||
it "is valid when built from factory" do
|
||||
e = build(:enterprise_group)
|
||||
e.should be_valid
|
||||
end
|
||||
|
||||
it "replace empty permalink and pass" do
|
||||
e = build(:enterprise_group, permalink: '')
|
||||
e.should be_valid
|
||||
e.permalink.should == e.name.parameterize
|
||||
end
|
||||
|
||||
it "restores permalink and pass" do
|
||||
e = create(:enterprise_group, permalink: 'p')
|
||||
e.permalink = ''
|
||||
e.should be_valid
|
||||
e.permalink.should == 'p'
|
||||
end
|
||||
|
||||
it "requires a name" do
|
||||
e = build(:enterprise_group, name: '')
|
||||
e.should_not be_valid
|
||||
@@ -60,5 +81,39 @@ describe EnterpriseGroup do
|
||||
|
||||
EnterpriseGroup.managed_by(user).should == [eg1]
|
||||
end
|
||||
|
||||
describe "finding a permalink" do
|
||||
it "finds available permalink" do
|
||||
existing = []
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink")).to eq "permalink"
|
||||
end
|
||||
|
||||
it "finds available permalink similar to existing" do
|
||||
existing = ["permalink1"]
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink")).to eq "permalink"
|
||||
end
|
||||
|
||||
it "adds unique number to existing permalinks" do
|
||||
existing = ["permalink"]
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink")).to eq "permalink1"
|
||||
existing = ["permalink", "permalink1"]
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink")).to eq "permalink2"
|
||||
end
|
||||
|
||||
it "ignores permalinks with characters after the index value" do
|
||||
existing = ["permalink", "permalink1", "permalink2xxx"]
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink")).to eq "permalink2"
|
||||
end
|
||||
|
||||
it "finds gaps in the indices of existing permalinks" do
|
||||
existing = ["permalink", "permalink1", "permalink3"]
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink")).to eq "permalink2"
|
||||
end
|
||||
|
||||
it "finds available indexed permalink" do
|
||||
existing = ["permalink", "permalink1"]
|
||||
expect(EnterpriseGroup.find_available_value(existing, "permalink1")).to eq "permalink11"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ describe EnterpriseRelationship do
|
||||
it "creates permissions with a list" do
|
||||
er = EnterpriseRelationship.create! parent: e1, child: e2, permissions_list: ['one', 'two']
|
||||
er.reload
|
||||
er.permissions.map(&:name).sort.should == ['one', 'two'].sort
|
||||
er.permissions.map(&:name).should match_array ['one', 'two']
|
||||
end
|
||||
|
||||
it "does nothing when the list is nil" do
|
||||
@@ -50,11 +50,11 @@ describe EnterpriseRelationship do
|
||||
let!(:er3) { create(:enterprise_relationship, parent: e1, child: e3) }
|
||||
|
||||
it "finds relationships that grant permissions to some enterprises" do
|
||||
EnterpriseRelationship.permitting([e1, e2]).sort.should == [er1, er2].sort
|
||||
EnterpriseRelationship.permitting([e1, e2]).should match_array [er1, er2]
|
||||
end
|
||||
|
||||
it "finds relationships that are granted by particular enterprises" do
|
||||
EnterpriseRelationship.permitted_by([e1, e2]).sort.should == [er1, er3].sort
|
||||
EnterpriseRelationship.permitted_by([e1, e2]).should match_array [er1, er3]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,7 +66,7 @@ describe EnterpriseRelationship do
|
||||
er3 = create(:enterprise_relationship, parent: e3, child: e1,
|
||||
permissions_list: ['three', 'four'])
|
||||
|
||||
EnterpriseRelationship.with_permission('two').sort.should == [er1, er2].sort
|
||||
EnterpriseRelationship.with_permission('two').should match_array [er1, er2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,7 +118,7 @@ describe Enterprise do
|
||||
let!(:er2) { create(:enterprise_relationship, parent_id: e.id, child_id: c.id) }
|
||||
|
||||
it "finds relatives" do
|
||||
e.relatives.sort.should == [p, c].sort
|
||||
e.relatives.should match_array [p, c]
|
||||
end
|
||||
|
||||
it "scopes relatives to visible distributors" do
|
||||
@@ -422,7 +422,7 @@ describe Enterprise do
|
||||
create(:product, :distributors => [d1], :on_hand => 5)
|
||||
create(:product, :distributors => [d3], :on_hand => 0)
|
||||
|
||||
Enterprise.with_distributed_active_products_on_hand.sort.should == [d1, d2]
|
||||
Enterprise.with_distributed_active_products_on_hand.should match_array [d1, d2]
|
||||
end
|
||||
|
||||
it "returns distributors with available products in stock" do
|
||||
@@ -438,7 +438,7 @@ describe Enterprise do
|
||||
create(:product, :distributors => [d4], :on_hand => 0)
|
||||
create(:product, :distributors => [d5]).delete
|
||||
|
||||
Enterprise.with_distributed_active_products_on_hand.sort.should == [d1, d2]
|
||||
Enterprise.with_distributed_active_products_on_hand.should match_array [d1, d2]
|
||||
Enterprise.with_distributed_active_products_on_hand.distinct_count.should == 2
|
||||
end
|
||||
end
|
||||
@@ -458,7 +458,7 @@ describe Enterprise do
|
||||
create(:product, :supplier => d4, :on_hand => 0)
|
||||
create(:product, :supplier => d5).delete
|
||||
|
||||
Enterprise.with_supplied_active_products_on_hand.sort.should == [d1, d2]
|
||||
Enterprise.with_supplied_active_products_on_hand.should match_array [d1, d2]
|
||||
Enterprise.with_supplied_active_products_on_hand.distinct_count.should == 2
|
||||
end
|
||||
end
|
||||
@@ -485,7 +485,7 @@ describe Enterprise do
|
||||
p1 = create(:simple_product, supplier: s1)
|
||||
p2 = create(:simple_product, supplier: s2)
|
||||
|
||||
Enterprise.supplying_variant_in([p1.master, p2.master]).sort.should == [s1, s2].sort
|
||||
Enterprise.supplying_variant_in([p1.master, p2.master]).should match_array [s1, s2]
|
||||
end
|
||||
|
||||
it "does not return duplicates" do
|
||||
@@ -625,9 +625,9 @@ describe Enterprise do
|
||||
er = EnterpriseRelationship.where(parent_id: opts[:from], child_id: opts[:to]).last
|
||||
er.should_not be_nil
|
||||
if opts[:with] == :all_permissions
|
||||
er.permissions.map(&:name).sort.should == ['add_to_order_cycle', 'manage_products', 'edit_profile', 'create_variant_overrides'].sort
|
||||
er.permissions.map(&:name).should match_array ['add_to_order_cycle', 'manage_products', 'edit_profile', 'create_variant_overrides']
|
||||
elsif opts.key? :with
|
||||
er.permissions.map(&:name).sort.should == opts[:with].map(&:to_s).sort
|
||||
er.permissions.map(&:name).should match_array opts[:with].map(&:to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -664,45 +664,38 @@ describe Enterprise do
|
||||
end
|
||||
|
||||
describe "finding variants distributed by the enterprise" do
|
||||
it "finds the master variant" do
|
||||
it "finds master and other variants" do
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product, distributors: [d])
|
||||
d.distributed_variants.should == [p.master]
|
||||
v = p.variants.first
|
||||
d.distributed_variants.should match_array [p.master, v]
|
||||
end
|
||||
|
||||
it "finds other variants" do
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product, distributors: [d])
|
||||
v = create(:variant, product: p)
|
||||
d.distributed_variants.sort.should == [p.master, v].sort
|
||||
end
|
||||
|
||||
it "finds variants distributed by order cycle" do
|
||||
pending "finds variants distributed by order cycle" do
|
||||
# there isn't actually a method for this on Enterprise?
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product)
|
||||
oc = create(:simple_order_cycle, distributors: [d], variants: [p.master])
|
||||
d.distributed_variants.should == [p.master]
|
||||
v = p.variants.first
|
||||
oc = create(:simple_order_cycle, distributors: [d], variants: [v])
|
||||
|
||||
# This method doesn't do what this test says it does...
|
||||
d.distributed_variants.should match_array [v]
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding variants distributed by the enterprise in a product distribution only" do
|
||||
it "finds the master variant" do
|
||||
it "finds master and other variants" do
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product, distributors: [d])
|
||||
d.product_distribution_variants.should == [p.master]
|
||||
end
|
||||
|
||||
it "finds other variants" do
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product, distributors: [d])
|
||||
v = create(:variant, product: p)
|
||||
d.product_distribution_variants.sort.should == [p.master, v].sort
|
||||
v = p.variants.first
|
||||
d.product_distribution_variants.should match_array [p.master, v]
|
||||
end
|
||||
|
||||
it "does not find variants distributed by order cycle" do
|
||||
d = create(:distributor_enterprise)
|
||||
p = create(:product)
|
||||
oc = create(:simple_order_cycle, distributors: [d], variants: [p.master])
|
||||
v = p.variants.first
|
||||
oc = create(:simple_order_cycle, distributors: [d], variants: [v])
|
||||
d.product_distribution_variants.should == []
|
||||
end
|
||||
end
|
||||
@@ -752,12 +745,12 @@ describe Enterprise do
|
||||
|
||||
it "gets all taxons of all distributed products" do
|
||||
Spree::Product.stub(:in_distributor).and_return [product1, product2]
|
||||
distributor.distributed_taxons.sort.should == [taxon1, taxon2].sort
|
||||
distributor.distributed_taxons.should match_array [taxon1, taxon2]
|
||||
end
|
||||
|
||||
it "gets all taxons of all supplied products" do
|
||||
Spree::Product.stub(:in_supplier).and_return [product1, product2]
|
||||
supplier.supplied_taxons.sort.should == [taxon1, taxon2].sort
|
||||
supplier.supplied_taxons.should match_array [taxon1, taxon2]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -845,6 +838,11 @@ describe Enterprise do
|
||||
expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2"
|
||||
end
|
||||
|
||||
it "finds available permalink similar to existing" do
|
||||
create(:enterprise, permalink: "permalink2xxx")
|
||||
expect(Enterprise.find_available_permalink("permalink2")).to eq "permalink2"
|
||||
end
|
||||
|
||||
it "finds gaps in the indices of existing permalinks" do
|
||||
create(:enterprise, permalink: "permalink3")
|
||||
expect(Enterprise.find_available_permalink("permalink")).to eq "permalink2"
|
||||
|
||||
@@ -170,17 +170,17 @@ describe Exchange do
|
||||
|
||||
it "finds exchanges coming from any of a number of enterprises" do
|
||||
Exchange.from_enterprises([coordinator]).should == [outgoing_exchange]
|
||||
Exchange.from_enterprises([supplier, coordinator]).sort.should == [incoming_exchange, outgoing_exchange].sort
|
||||
Exchange.from_enterprises([supplier, coordinator]).should match_array [incoming_exchange, outgoing_exchange]
|
||||
end
|
||||
|
||||
it "finds exchanges going to any of a number of enterprises" do
|
||||
Exchange.to_enterprises([coordinator]).should == [incoming_exchange]
|
||||
Exchange.to_enterprises([coordinator, distributor]).sort.should == [incoming_exchange, outgoing_exchange].sort
|
||||
Exchange.to_enterprises([coordinator, distributor]).should match_array [incoming_exchange, outgoing_exchange]
|
||||
end
|
||||
|
||||
it "finds exchanges involving any of a number of enterprises" do
|
||||
Exchange.involving([supplier]).should == [incoming_exchange]
|
||||
Exchange.involving([coordinator]).sort.should == [incoming_exchange, outgoing_exchange].sort
|
||||
Exchange.involving([coordinator]).should match_array [incoming_exchange, outgoing_exchange]
|
||||
Exchange.involving([distributor]).should == [outgoing_exchange]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,7 +37,7 @@ describe OrderCycle do
|
||||
oc_undated = create(:simple_order_cycle, orders_open_at: nil, orders_close_at: nil)
|
||||
|
||||
OrderCycle.active.should == [oc_active]
|
||||
OrderCycle.inactive.sort.should == [oc_not_yet_open, oc_already_closed].sort
|
||||
OrderCycle.inactive.should match_array [oc_not_yet_open, oc_already_closed]
|
||||
OrderCycle.upcoming.should == [oc_not_yet_open]
|
||||
OrderCycle.closed.should == [oc_already_closed]
|
||||
OrderCycle.undated.should == [oc_undated]
|
||||
@@ -153,7 +153,7 @@ describe OrderCycle do
|
||||
e2 = create(:exchange, incoming: true,
|
||||
order_cycle: oc, receiver: oc.coordinator, sender: create(:enterprise))
|
||||
|
||||
oc.suppliers.sort.should == [e1.sender, e2.sender].sort
|
||||
oc.suppliers.should match_array [e1.sender, e2.sender]
|
||||
end
|
||||
|
||||
it "reports its distributors" do
|
||||
@@ -164,7 +164,7 @@ describe OrderCycle do
|
||||
e2 = create(:exchange, incoming: false,
|
||||
order_cycle: oc, sender: oc.coordinator, receiver: create(:enterprise))
|
||||
|
||||
oc.distributors.sort.should == [e1.receiver, e2.receiver].sort
|
||||
oc.distributors.should match_array [e1.receiver, e2.receiver]
|
||||
end
|
||||
|
||||
it "checks for existance of distributors" do
|
||||
@@ -215,11 +215,11 @@ describe OrderCycle do
|
||||
end
|
||||
|
||||
it "reports on the variants exchanged" do
|
||||
@oc.variants.sort.should == [@p0.master, @p1.master, @p2.master, @p2_v].sort
|
||||
@oc.variants.should match_array [@p0.master, @p1.master, @p2.master, @p2_v]
|
||||
end
|
||||
|
||||
it "reports on the variants distributed" do
|
||||
@oc.distributed_variants.sort.should == [@p1.master, @p2.master, @p2_v].sort
|
||||
@oc.distributed_variants.should match_array [@p1.master, @p2.master, @p2_v]
|
||||
end
|
||||
|
||||
it "reports on the variants distributed by a particular distributor" do
|
||||
@@ -231,7 +231,7 @@ describe OrderCycle do
|
||||
end
|
||||
|
||||
it "reports on the products exchanged" do
|
||||
@oc.products.sort.should == [@p0, @p1, @p2]
|
||||
@oc.products.should match_array [@p0, @p1, @p2]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -239,10 +239,12 @@ describe OrderCycle do
|
||||
it "returns valid products but not invalid products" do
|
||||
p_valid = create(:product)
|
||||
p_invalid = create(:product)
|
||||
v = create(:variant, product: p_invalid)
|
||||
v_valid = p_valid.variants.first
|
||||
v_invalid = p_invalid.variants.first
|
||||
|
||||
d = create(:distributor_enterprise)
|
||||
oc = create(:simple_order_cycle, distributors: [d], variants: [p_valid.master, p_invalid.master])
|
||||
oc = create(:simple_order_cycle, distributors: [d], variants: [v_valid, p_invalid.master])
|
||||
|
||||
oc.valid_products_distributed_by(d).should == [p_valid]
|
||||
end
|
||||
|
||||
@@ -313,7 +315,7 @@ describe OrderCycle do
|
||||
@oc.pickup_time_for(@d2).should == '2-8pm Friday'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "finding pickup instructions for a distributor" do
|
||||
it "returns the pickup instructions" do
|
||||
@oc.pickup_instructions_for(@d1).should == "Come get it!"
|
||||
@@ -375,7 +377,7 @@ describe OrderCycle do
|
||||
|
||||
occ.coordinator_fee_ids.should_not be_empty
|
||||
occ.coordinator_fee_ids.should == oc.coordinator_fee_ids
|
||||
|
||||
|
||||
# to_h gives us a unique hash for each exchange
|
||||
# check that the clone has no additional exchanges
|
||||
occ.exchanges.map(&:to_h).all? do |ex|
|
||||
@@ -402,7 +404,7 @@ describe OrderCycle do
|
||||
describe "finding order cycles opening in the future" do
|
||||
it "should give the soonest opening order cycle for a distributor" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
oc = create(:simple_order_cycle, name: 'oc 1', distributors: [distributor], orders_open_at: 10.days.from_now, orders_close_at: 11.days.from_now)
|
||||
oc = create(:simple_order_cycle, name: 'oc 1', distributors: [distributor], orders_open_at: 10.days.from_now, orders_close_at: 11.days.from_now)
|
||||
OrderCycle.first_opening_for(distributor).should == oc
|
||||
end
|
||||
|
||||
@@ -411,12 +413,12 @@ describe OrderCycle do
|
||||
OrderCycle.first_opening_for(distributor).should == nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "finding open order cycles" do
|
||||
it "should give the soonest closing order cycle for a distributor" do
|
||||
distributor = create(:distributor_enterprise)
|
||||
oc = create(:simple_order_cycle, name: 'oc 1', distributors: [distributor], orders_open_at: 1.days.ago, orders_close_at: 11.days.from_now)
|
||||
oc2 = create(:simple_order_cycle, name: 'oc 2', distributors: [distributor], orders_open_at: 2.days.ago, orders_close_at: 12.days.from_now)
|
||||
oc = create(:simple_order_cycle, name: 'oc 1', distributors: [distributor], orders_open_at: 1.days.ago, orders_close_at: 11.days.from_now)
|
||||
oc2 = create(:simple_order_cycle, name: 'oc 2', distributors: [distributor], orders_open_at: 2.days.ago, orders_close_at: 12.days.from_now)
|
||||
OrderCycle.first_closing_for(distributor).should == oc
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ module Spree
|
||||
it "finds line items for products supplied by one of a number of enterprises" do
|
||||
LineItem.supplied_by_any([s1]).should == [li1]
|
||||
LineItem.supplied_by_any([s2]).should == [li2]
|
||||
LineItem.supplied_by_any([s1, s2]).sort.should == [li1, li2].sort
|
||||
LineItem.supplied_by_any([s1, s2]).should match_array [li1, li2]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ module Spree
|
||||
let(:payment) { create(:payment, source: create(:credit_card)) }
|
||||
|
||||
it "can capture and void" do
|
||||
payment.actions.sort.should == %w(capture void).sort
|
||||
payment.actions.should match_array %w(capture void)
|
||||
end
|
||||
|
||||
describe "when a payment has been taken" do
|
||||
@@ -17,7 +17,7 @@ module Spree
|
||||
end
|
||||
|
||||
it "can void and credit" do
|
||||
payment.actions.sort.should == %w(void credit).sort
|
||||
payment.actions.should match_array %w(void credit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -25,9 +25,11 @@ module Spree
|
||||
it "does not save when master is invalid" do
|
||||
s = create(:supplier_enterprise)
|
||||
t = create(:taxon)
|
||||
product = Product.new supplier_id: s.id, name: "Apples", price: 1, primary_taxon_id: t.id
|
||||
product = Product.new supplier_id: s.id, name: "Apples", price: 1, primary_taxon_id: t.id, variant_unit: "weight", variant_unit_scale: 1000, unit_value: 1
|
||||
product.on_hand = "10,000"
|
||||
product.save.should be_false
|
||||
expect(product.save).to be_false
|
||||
|
||||
expect(product.errors[:count_on_hand]).to include "is not a number"
|
||||
end
|
||||
|
||||
it "defaults available_on to now" do
|
||||
@@ -55,6 +57,14 @@ module Spree
|
||||
end
|
||||
|
||||
|
||||
it "does not allow the last variant to be deleted" do
|
||||
product = create(:simple_product)
|
||||
expect(product.variants(:reload).length).to eq 1
|
||||
v = product.variants.last
|
||||
v.delete
|
||||
expect(v.errors[:product]).to include "must have at least one variant"
|
||||
end
|
||||
|
||||
context "when the product has variants" do
|
||||
let(:product) do
|
||||
product = create(:simple_product)
|
||||
@@ -85,6 +95,34 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
context "saving a new product" do
|
||||
let!(:product){ Spree::Product.new }
|
||||
|
||||
before do
|
||||
product.primary_taxon = create(:taxon)
|
||||
product.supplier = create(:supplier_enterprise)
|
||||
product.name = "Product1"
|
||||
product.variant_unit = "weight"
|
||||
product.variant_unit_scale = 1000
|
||||
product.unit_value = 1
|
||||
product.on_hand = 3
|
||||
product.price = 4.27
|
||||
product.save!
|
||||
end
|
||||
|
||||
it "copies the properties on master variant to the first standard variant" do
|
||||
expect(product.variants(:reload).length).to eq 1
|
||||
standard_variant = product.variants(:reload).first
|
||||
expect(standard_variant.price).to eq product.master.price
|
||||
end
|
||||
|
||||
it "only duplicates master with after_save when no standard variants exist" do
|
||||
expect(product).to receive :ensure_standard_variant
|
||||
product.name = "Something else"
|
||||
expect{product.save!}.to_not change{product.variants.count}
|
||||
end
|
||||
end
|
||||
|
||||
context "when the unit is items" do
|
||||
it "is valid when unit name is set and unit scale is not" do
|
||||
product.variant_unit = 'items'
|
||||
@@ -102,15 +140,15 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
context "when product does not have variants" do
|
||||
context "a basic product" do
|
||||
let(:product) { create(:simple_product) }
|
||||
|
||||
it "does not require any variant unit fields" do
|
||||
it "requires variant unit fields" do
|
||||
product.variant_unit = nil
|
||||
product.variant_unit_name = nil
|
||||
product.variant_unit_scale = nil
|
||||
|
||||
product.should be_valid
|
||||
expect(product).to be_invalid
|
||||
end
|
||||
|
||||
it "requires a unit scale when variant unit is weight" do
|
||||
@@ -123,7 +161,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "scopes" do
|
||||
describe "in_supplier" do
|
||||
it "shows products in supplier" do
|
||||
@@ -421,63 +458,6 @@ module Spree
|
||||
|
||||
|
||||
describe "variant units" do
|
||||
context "when the product initially has no variant unit" do
|
||||
let!(:p) { create(:simple_product,
|
||||
variant_unit: nil,
|
||||
variant_unit_scale: nil,
|
||||
variant_unit_name: nil) }
|
||||
|
||||
context "when the required option type does not exist" do
|
||||
it "creates the option type and assigns it to the product" do
|
||||
expect {
|
||||
p.update_attributes!(variant_unit: 'weight', variant_unit_scale: 1000)
|
||||
}.to change(Spree::OptionType, :count).by(1)
|
||||
|
||||
ot = Spree::OptionType.last
|
||||
ot.name.should == 'unit_weight'
|
||||
ot.presentation.should == 'Weight'
|
||||
|
||||
p.option_types.should == [ot]
|
||||
end
|
||||
|
||||
it "does the same with volume" do
|
||||
expect {
|
||||
p.update_attributes!(variant_unit: 'volume', variant_unit_scale: 1000)
|
||||
}.to change(Spree::OptionType, :count).by(1)
|
||||
|
||||
ot = Spree::OptionType.last
|
||||
ot.name.should == 'unit_volume'
|
||||
ot.presentation.should == 'Volume'
|
||||
|
||||
p.option_types.should == [ot]
|
||||
end
|
||||
|
||||
it "does the same with items" do
|
||||
expect {
|
||||
p.update_attributes!(variant_unit: 'items', variant_unit_name: 'packet')
|
||||
}.to change(Spree::OptionType, :count).by(1)
|
||||
|
||||
ot = Spree::OptionType.last
|
||||
ot.name.should == 'unit_items'
|
||||
ot.presentation.should == 'Items'
|
||||
|
||||
p.option_types.should == [ot]
|
||||
end
|
||||
end
|
||||
|
||||
context "when the required option type already exists" do
|
||||
let!(:ot) { create(:option_type, name: 'unit_weight', presentation: 'Weight') }
|
||||
|
||||
it "looks up the option type and assigns it to the product" do
|
||||
expect {
|
||||
p.update_attributes!(variant_unit: 'weight', variant_unit_scale: 1000)
|
||||
}.to change(Spree::OptionType, :count).by(0)
|
||||
|
||||
p.option_types.should == [ot]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the product already has a variant unit set (and all required option types exist)" do
|
||||
let!(:p) { create(:simple_product,
|
||||
variant_unit: 'weight',
|
||||
@@ -491,11 +471,6 @@ module Spree
|
||||
p.option_types.should == [ot_volume]
|
||||
end
|
||||
|
||||
it "leaves option type unassigned if none is provided" do
|
||||
p.update_attributes!(variant_unit: nil, variant_unit_scale: nil)
|
||||
p.option_types.should == []
|
||||
end
|
||||
|
||||
it "does not remove and re-add the option type if it is not changed" do
|
||||
p.option_types.should_receive(:delete).never
|
||||
p.update_attributes!(name: 'foo')
|
||||
@@ -532,20 +507,13 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
describe "returning the variant unit option type" do
|
||||
it "returns nil when variant_unit is not set" do
|
||||
p = create(:simple_product, variant_unit: nil)
|
||||
p.variant_unit_option_type.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it "finds all variant unit option types" do
|
||||
ot1 = create(:option_type, name: 'unit_weight', presentation: 'Weight')
|
||||
ot2 = create(:option_type, name: 'unit_volume', presentation: 'Volume')
|
||||
ot3 = create(:option_type, name: 'unit_items', presentation: 'Items')
|
||||
ot4 = create(:option_type, name: 'foo_unit_bar', presentation: 'Foo')
|
||||
|
||||
Spree::Product.all_variant_unit_option_types.sort.should == [ot1, ot2, ot3].sort
|
||||
Spree::Product.all_variant_unit_option_types.should match_array [ot1, ot2, ot3]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -586,16 +554,6 @@ module Spree
|
||||
end
|
||||
|
||||
describe "finding products in stock for a particular distribution" do
|
||||
it "returns in-stock products without variants" do
|
||||
p = create(:simple_product)
|
||||
p.master.update_attribute(:count_on_hand, 1)
|
||||
d = create(:distributor_enterprise)
|
||||
oc = create(:simple_order_cycle, distributors: [d])
|
||||
oc.exchanges.outgoing.first.variants << p.master
|
||||
|
||||
p.should have_stock_for_distribution(oc, d)
|
||||
end
|
||||
|
||||
it "returns on-demand products" do
|
||||
p = create(:simple_product, on_demand: true)
|
||||
p.master.update_attribute(:count_on_hand, 0)
|
||||
|
||||
@@ -15,7 +15,7 @@ module Spree
|
||||
sm.distributors << d1
|
||||
sm.distributors << d2
|
||||
|
||||
sm.reload.distributors.sort.should == [d1, d2].sort
|
||||
sm.reload.distributors.should match_array [d1, d2]
|
||||
end
|
||||
|
||||
it "finds shipping methods for a particular distributor" do
|
||||
|
||||
@@ -14,7 +14,7 @@ module Spree
|
||||
|
||||
describe "finding variants in stock" do
|
||||
before do
|
||||
p = create(:product)
|
||||
p = create(:product, on_hand: 0)
|
||||
@v_in_stock = create(:variant, product: p)
|
||||
@v_on_demand = create(:variant, product: p, on_demand: true)
|
||||
@v_no_stock = create(:variant, product: p)
|
||||
@@ -25,7 +25,7 @@ module Spree
|
||||
end
|
||||
|
||||
it "returns variants in stock or on demand, but not those that are neither" do
|
||||
Variant.where(is_master: false).in_stock.sort.should == [@v_in_stock, @v_on_demand].sort
|
||||
Variant.where(is_master: false).in_stock.should match_array [@v_in_stock, @v_on_demand]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -239,17 +239,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
context "when the product does not have variants" do
|
||||
let(:product) { create(:simple_product, variant_unit: nil) }
|
||||
let(:variant) { product.master }
|
||||
|
||||
it "does not require unit value or unit description when the product's unit is empty" do
|
||||
variant.unit_value = nil
|
||||
variant.unit_description = nil
|
||||
variant.should be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe "unit value/description" do
|
||||
describe "getting name for display" do
|
||||
it "returns display_name if present" do
|
||||
@@ -283,7 +272,7 @@ module Spree
|
||||
|
||||
describe "setting the variant's weight from the unit value" do
|
||||
it "sets the variant's weight when unit is weight" do
|
||||
p = create(:simple_product, variant_unit: nil, variant_unit_scale: nil)
|
||||
p = create(:simple_product, variant_unit: 'volume')
|
||||
v = create(:variant, product: p, weight: nil)
|
||||
|
||||
p.update_attributes! variant_unit: 'weight', variant_unit_scale: 1
|
||||
@@ -293,7 +282,7 @@ module Spree
|
||||
end
|
||||
|
||||
it "does nothing when unit is not weight" do
|
||||
p = create(:simple_product, variant_unit: nil, variant_unit_scale: nil)
|
||||
p = create(:simple_product, variant_unit: 'volume')
|
||||
v = create(:variant, product: p, weight: 123)
|
||||
|
||||
p.update_attributes! variant_unit: 'volume', variant_unit_scale: 1
|
||||
@@ -303,7 +292,7 @@ module Spree
|
||||
end
|
||||
|
||||
it "does nothing when unit_value is not set" do
|
||||
p = create(:simple_product, variant_unit: nil, variant_unit_scale: nil)
|
||||
p = create(:simple_product, variant_unit: 'volume')
|
||||
v = create(:variant, product: p, weight: 123)
|
||||
|
||||
p.update_attributes! variant_unit: 'weight', variant_unit_scale: 1
|
||||
@@ -316,56 +305,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
context "when the variant initially has no value" do
|
||||
context "when the required option value does not exist" do
|
||||
let!(:p) { create(:simple_product, variant_unit: nil, variant_unit_scale: nil) }
|
||||
let!(:v) { create(:variant, product: p, unit_value: nil, unit_description: nil) }
|
||||
|
||||
before do
|
||||
p.update_attributes!(variant_unit: 'weight', variant_unit_scale: 1)
|
||||
@ot = Spree::OptionType.find_by_name 'unit_weight'
|
||||
end
|
||||
|
||||
it "creates the option value and assigns it to the variant" do
|
||||
expect {
|
||||
v.update_attributes!(unit_value: 10, unit_description: 'foo')
|
||||
}.to change(Spree::OptionValue, :count).by(1)
|
||||
|
||||
ov = Spree::OptionValue.last
|
||||
ov.option_type.should == @ot
|
||||
ov.name.should == '10g foo'
|
||||
ov.presentation.should == '10g foo'
|
||||
|
||||
v.option_values.should include ov
|
||||
end
|
||||
end
|
||||
|
||||
context "when the required option value already exists" do
|
||||
let!(:p_orig) { create(:simple_product, variant_unit: 'weight', variant_unit_scale: 1) }
|
||||
let!(:v_orig) { create(:variant, product: p_orig, unit_value: 10, unit_description: 'foo') }
|
||||
|
||||
let!(:p) { create(:simple_product, variant_unit: nil, variant_unit_scale: nil) }
|
||||
let!(:v) { create(:variant, product: p, unit_value: nil, unit_description: nil) }
|
||||
|
||||
before do
|
||||
p.update_attributes!(variant_unit: 'weight', variant_unit_scale: 1)
|
||||
@ot = Spree::OptionType.find_by_name 'unit_weight'
|
||||
end
|
||||
|
||||
it "looks up the option value and assigns it to the variant" do
|
||||
expect {
|
||||
v.update_attributes!(unit_value: 10, unit_description: 'foo')
|
||||
}.to change(Spree::OptionValue, :count).by(0)
|
||||
|
||||
ov = v.option_values.last
|
||||
ov.option_type.should == @ot
|
||||
ov.name.should == '10g foo'
|
||||
ov.presentation.should == '10g foo'
|
||||
|
||||
v_orig.option_values.should include ov
|
||||
end
|
||||
end
|
||||
end
|
||||
context "when the variant already has a value set (and all required option values exist)" do
|
||||
let!(:p0) { create(:simple_product, variant_unit: 'weight', variant_unit_scale: 1) }
|
||||
let!(:v0) { create(:variant, product: p0, unit_value: 10, unit_description: 'foo') }
|
||||
@@ -460,5 +399,22 @@ module Spree
|
||||
v.destroy
|
||||
e.reload.variant_ids.should be_empty
|
||||
end
|
||||
|
||||
context "as the last variant of a product" do
|
||||
let!(:extra_variant) { create(:variant) }
|
||||
let!(:product) { extra_variant.product }
|
||||
let!(:first_variant) { product.variants.first }
|
||||
|
||||
before { product.reload }
|
||||
|
||||
it "cannot be deleted" do
|
||||
expect(product.variants.length).to eq 2
|
||||
expect(extra_variant.delete).to eq extra_variant
|
||||
expect(product.variants(:reload).length).to eq 1
|
||||
expect(first_variant.delete).to be_false
|
||||
expect(product.variants(:reload).length).to eq 1
|
||||
expect(first_variant.errors[:product]).to include "must have at least one variant"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ describe VariantOverride do
|
||||
let!(:vo2) { create(:variant_override, hub: hub2, variant: v) }
|
||||
|
||||
it "finds variant overrides for a set of hubs" do
|
||||
VariantOverride.for_hubs([hub1, hub2]).sort.should == [vo1, vo2].sort
|
||||
VariantOverride.for_hubs([hub1, hub2]).should match_array [vo1, vo2]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -7,72 +7,57 @@ describe "Shop API" do
|
||||
let(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) }
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
let(:oc1) { create(:simple_order_cycle, distributors: [distributor], coordinator: create(:distributor_enterprise), orders_close_at: 2.days.from_now) }
|
||||
let(:p1) { create(:simple_product, on_demand: false) }
|
||||
let(:p2) { create(:simple_product, on_demand: true) }
|
||||
let(:p3) { create(:simple_product, on_demand: false) }
|
||||
let(:p4) { create(:simple_product, on_demand: false) }
|
||||
let(:p5) { create(:simple_product, on_demand: false) }
|
||||
let(:p6) { create(:simple_product, on_demand: false) }
|
||||
let(:p7) { create(:simple_product, on_demand: false) }
|
||||
let(:v1) { create(:variant, product: p4, unit_value: 2) }
|
||||
let(:v2) { create(:variant, product: p4, unit_value: 3, on_demand: false) }
|
||||
let(:v3) { create(:variant, product: p4, unit_value: 4, on_demand: true) }
|
||||
let(:v4) { create(:variant, product: p5) }
|
||||
let(:v5) { create(:variant, product: p5) }
|
||||
let(:v6) { create(:variant, product: p7) }
|
||||
let(:v41) { p4.variants.first }
|
||||
let(:v42) { create(:variant, product: p4, unit_value: 3, on_demand: false) }
|
||||
let(:v43) { create(:variant, product: p4, unit_value: 4, on_demand: true) }
|
||||
let(:v51) { p5.variants.first }
|
||||
let(:v52) { create(:variant, product: p5) }
|
||||
let(:v61) { p6.variants.first }
|
||||
let(:v71) { p7.variants.first }
|
||||
let(:order) { create(:order, distributor: distributor, order_cycle: oc1) }
|
||||
|
||||
before do
|
||||
set_order order
|
||||
|
||||
p1.master.update_attribute(:count_on_hand, 1)
|
||||
p2.master.update_attribute(:count_on_hand, 0)
|
||||
p3.master.update_attribute(:count_on_hand, 0)
|
||||
p6.master.update_attribute(:count_on_hand, 1)
|
||||
v61.update_attribute(:count_on_hand, 1)
|
||||
p6.delete
|
||||
p7.master.update_attribute(:count_on_hand, 1)
|
||||
v1.update_attribute(:count_on_hand, 1)
|
||||
v2.update_attribute(:count_on_hand, 0)
|
||||
v3.update_attribute(:count_on_hand, 0)
|
||||
v4.update_attribute(:count_on_hand, 1)
|
||||
v5.update_attribute(:count_on_hand, 0)
|
||||
v6.update_attribute(:count_on_hand, 1)
|
||||
v6.update_attribute(:deleted_at, Time.now)
|
||||
exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
|
||||
exchange.update_attribute :pickup_time, "frogs"
|
||||
exchange.variants << p1.master
|
||||
exchange.variants << p2.master
|
||||
exchange.variants << p3.master
|
||||
exchange.variants << p6.master
|
||||
exchange.variants << v1
|
||||
exchange.variants << v2
|
||||
exchange.variants << v3
|
||||
# v4 is in stock but not in distribution
|
||||
# v5 is out of stock and in the distribution
|
||||
v71.update_attribute(:count_on_hand, 1)
|
||||
v41.update_attribute(:count_on_hand, 1)
|
||||
v42.update_attribute(:count_on_hand, 0)
|
||||
v43.update_attribute(:count_on_hand, 0)
|
||||
v51.update_attribute(:count_on_hand, 1)
|
||||
v52.update_attribute(:count_on_hand, 0)
|
||||
v71.update_attribute(:count_on_hand, 1)
|
||||
v71.update_attribute(:deleted_at, Time.now)
|
||||
exchange = Exchange.find(oc1.exchanges.to_enterprises(distributor).outgoing.first.id)
|
||||
exchange.update_attribute :pickup_time, "frogs"
|
||||
exchange.variants << v61
|
||||
exchange.variants << v41
|
||||
exchange.variants << v42
|
||||
exchange.variants << v43
|
||||
# v51 is in stock but not in distribution
|
||||
# v52 is out of stock and in the distribution
|
||||
# Neither should display, nor should their product, p5
|
||||
exchange.variants << v5
|
||||
exchange.variants << v6
|
||||
exchange.variants << v52
|
||||
exchange.variants << v71
|
||||
get products_shop_path
|
||||
end
|
||||
|
||||
it "filters products based on availability" do
|
||||
# It shows on hand products
|
||||
response.body.should include p1.name
|
||||
response.body.should include p4.name
|
||||
# It shows on demand products
|
||||
response.body.should include p2.name
|
||||
# It does not show products that are neither on hand or on demand
|
||||
response.body.should_not include p3.name
|
||||
# It shows on demand variants
|
||||
response.body.should include v3.options_text
|
||||
response.body.should include v43.options_text
|
||||
# It does not show variants that are neither on hand or on demand
|
||||
response.body.should_not include v2.options_text
|
||||
response.body.should_not include v42.options_text
|
||||
# It does not show products that have no available variants in this distribution
|
||||
response.body.should_not include p5.name
|
||||
# It does not show deleted products
|
||||
response.body.should_not include p6.name
|
||||
# It does not show deleted variants
|
||||
response.body.should_not include v6.name
|
||||
response.body.should_not include v71.name
|
||||
response.body.should_not include p7.name
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user