mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-09 03:20:21 +00:00
Merge branch 'master' into admin-panel-store-link
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
angular.module("ofn.admin").controller "AdminEnterpriseRelationshipsCtrl", ($scope, EnterpriseRelationships, Enterprises) ->
|
||||
$scope.EnterpriseRelationships = EnterpriseRelationships
|
||||
$scope.Enterprises = Enterprises
|
||||
$scope.permissions = {}
|
||||
|
||||
$scope.create = ->
|
||||
$scope.EnterpriseRelationships.create($scope.parent_id, $scope.child_id)
|
||||
$scope.EnterpriseRelationships.create($scope.parent_id, $scope.child_id, $scope.permissions)
|
||||
|
||||
$scope.delete = (enterprise_relationship) ->
|
||||
if confirm("Are you sure?")
|
||||
|
||||
@@ -330,7 +330,7 @@ angular.module('order_cycle', ['ngResource'])
|
||||
}])
|
||||
|
||||
.factory('Enterprise', ['$resource', ($resource) ->
|
||||
Enterprise = $resource('/admin/enterprises/:enterprise_id.json', {}, {'index': {method: 'GET', isArray: true}})
|
||||
Enterprise = $resource('/admin/enterprises/for_order_cycle/:enterprise_id.json', {}, {'index': {method: 'GET', isArray: true}})
|
||||
|
||||
{
|
||||
Enterprise: Enterprise
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterprise_relationships) ->
|
||||
new class EnterpriseRelationships
|
||||
create_errors: ""
|
||||
all_permissions: [
|
||||
'add_to_order_cycle'
|
||||
'manage_products'
|
||||
]
|
||||
|
||||
constructor: ->
|
||||
@enterprise_relationships = enterprise_relationships
|
||||
|
||||
create: (parent_id, child_id) ->
|
||||
$http.post('/admin/enterprise_relationships', {enterprise_relationship: {parent_id: parent_id, child_id: child_id}}).success (data, status) =>
|
||||
create: (parent_id, child_id, permissions) ->
|
||||
permissions = (name for name, enabled of permissions when enabled)
|
||||
$http.post('/admin/enterprise_relationships', {enterprise_relationship: {parent_id: parent_id, child_id: child_id, permissions_list: permissions}}).success (data, status) =>
|
||||
@enterprise_relationships.unshift(data)
|
||||
@create_errors = ""
|
||||
|
||||
@@ -16,3 +21,8 @@ angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterpris
|
||||
delete: (er) ->
|
||||
$http.delete('/admin/enterprise_relationships/' + er.id).success (data) =>
|
||||
@enterprise_relationships.splice @enterprise_relationships.indexOf(er), 1
|
||||
|
||||
permission_presentation: (permission) ->
|
||||
switch permission
|
||||
when "add_to_order_cycle" then "can add to order cycle"
|
||||
when "manage_products" then "can manage the products of"
|
||||
|
||||
@@ -6,7 +6,7 @@ Darkswarm.controller "PaymentCtrl", ($scope, $timeout) ->
|
||||
{key: "January", value: "1"},
|
||||
{key: "February", value: "2"},
|
||||
{key: "March", value: "3"},
|
||||
{key: "April", value: "4"},
|
||||
{key: "April", value: "4"},
|
||||
{key: "May", value: "5"},
|
||||
{key: "June", value: "6"},
|
||||
{key: "July", value: "7"},
|
||||
@@ -20,4 +20,4 @@ Darkswarm.controller "PaymentCtrl", ($scope, $timeout) ->
|
||||
$scope.years = [moment().year()..(moment().year()+15)]
|
||||
$scope.secrets.card_month = "1"
|
||||
$scope.secrets.card_year = moment().year()
|
||||
$timeout $scope.onTimeout
|
||||
$timeout $scope.onTimeout
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
window.FieldsetMixin = ($scope)->
|
||||
$scope.next = (event = false)->
|
||||
event.preventDefault() if event
|
||||
$scope.show $scope.nextPanel
|
||||
$scope.show $scope.nextPanel
|
||||
|
||||
$scope.onTimeout = ->
|
||||
if $scope[$scope.name].$valid
|
||||
@@ -36,7 +36,6 @@ window.FieldsetMixin = ($scope)->
|
||||
when "number" then "must be number"
|
||||
when "email" then "must be email address"
|
||||
|
||||
#server_errors = $scope.Order.errors[path.replace('order.', '')]
|
||||
#errors.push server_errors if server_errors?
|
||||
(errors.filter (error) -> error?).join ", "
|
||||
|
||||
#server_errors = $scope.Order.errors[path.replace('order.', '')]
|
||||
#errors.push server_errors if server_errors?
|
||||
(errors.filter (error) -> error?).join ", "
|
||||
@@ -32,6 +32,10 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h
|
||||
|
||||
if @ship_address_same_as_billing
|
||||
munged_order.ship_address_attributes = munged_order.bill_address_attributes
|
||||
# If the order already has a ship and bill address (as with logged in users with
|
||||
# past orders), and we don't remove id here, then this will set the wrong id for
|
||||
# ship address, and Rails will error with a 404 for that address.
|
||||
delete munged_order.ship_address_attributes.id
|
||||
|
||||
if @paymentMethod()?.method_type == 'gateway'
|
||||
angular.extend munged_order.payments_attributes[0], {
|
||||
|
||||
@@ -48,3 +48,4 @@ Darkswarm.factory 'Products', ($resource, Enterprises, Dereferencer, Taxons, Car
|
||||
|
||||
product.primaryImage = product.images[0]?.small_url if product.images
|
||||
product.primaryImageOrMissing = product.primaryImage || "/assets/noimage/small.png"
|
||||
product.largeImage = product.images[0]?.large_url if product.images
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.row
|
||||
.columns.small-12.large-6
|
||||
%img.product-img{"ng-src" => "{{product.primaryImage}}", "ng-if" => "product.primaryImage"}
|
||||
%img.product-img{"ng-src" => "{{product.largeImage}}", "ng-if" => "product.largeImage"}
|
||||
.columns.small-12.large-6.product-header
|
||||
%h2
|
||||
/ %render-svg{path: "{{product.primary_taxon.icon}}"}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
|
||||
table#enterprise-relationships, table#enterprise-roles
|
||||
ul
|
||||
list-style-type: none
|
||||
|
||||
th.actions, td.actions
|
||||
width: 16%
|
||||
.errors
|
||||
|
||||
@@ -10,7 +10,7 @@ module Admin
|
||||
@enterprise_relationship = EnterpriseRelationship.new params[:enterprise_relationship]
|
||||
|
||||
if @enterprise_relationship.save
|
||||
render partial: "admin/json/enterprise_relationship", locals: {enterprise_relationship: @enterprise_relationship}
|
||||
render text: Api::Admin::EnterpriseRelationshipSerializer.new(@enterprise_relationship).to_json
|
||||
else
|
||||
render status: 400, json: {errors: @enterprise_relationship.errors.full_messages.join(', ')}
|
||||
end
|
||||
|
||||
@@ -6,6 +6,11 @@ module Admin
|
||||
create.after :grant_management
|
||||
|
||||
helper 'spree/products'
|
||||
include OrderCyclesHelper
|
||||
|
||||
def for_order_cycle
|
||||
@collection = order_cycle_permitted_enterprises
|
||||
end
|
||||
|
||||
|
||||
def bulk_update
|
||||
@@ -53,7 +58,7 @@ module Admin
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index, :bulk_update]
|
||||
[:index, :for_order_cycle, :bulk_update]
|
||||
end
|
||||
|
||||
def load_methods_and_fees
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
require 'open_food_network/permissions'
|
||||
require 'open_food_network/order_cycle_form_applicator'
|
||||
|
||||
module Admin
|
||||
class OrderCyclesController < ResourceController
|
||||
include OrderCyclesHelper
|
||||
|
||||
before_filter :load_order_cycle_set, :only => :index
|
||||
|
||||
def show
|
||||
@@ -23,7 +26,7 @@ module Admin
|
||||
|
||||
respond_to do |format|
|
||||
if @order_cycle.save
|
||||
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, managed_enterprises).go!
|
||||
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, order_cycle_permitted_enterprises).go!
|
||||
|
||||
flash[:notice] = 'Your order cycle has been created.'
|
||||
format.html { redirect_to admin_order_cycles_path }
|
||||
@@ -40,7 +43,7 @@ module Admin
|
||||
|
||||
respond_to do |format|
|
||||
if @order_cycle.update_attributes(params[:order_cycle])
|
||||
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, managed_enterprises).go!
|
||||
OpenFoodNetwork::OrderCycleFormApplicator.new(@order_cycle, order_cycle_permitted_enterprises).go!
|
||||
|
||||
flash[:notice] = 'Your order cycle has been updated.'
|
||||
format.html { redirect_to admin_order_cycles_path }
|
||||
|
||||
@@ -30,6 +30,9 @@ Spree::Admin::ProductsController.class_eval do
|
||||
"#{string}q[#{filter[:property][:db_column]}_#{filter[:predicate][:predicate]}]=#{filter[:value]};"
|
||||
end
|
||||
|
||||
# Ensure we're authorised to update all products
|
||||
product_set.collection.each { |p| authorize! :update, p }
|
||||
|
||||
if product_set.save
|
||||
redirect_to "/api/products/bulk_products?page=1;per_page=500;#{bulk_index_query}"
|
||||
else
|
||||
@@ -85,7 +88,7 @@ Spree::Admin::ProductsController.class_eval do
|
||||
def load_bpe_data
|
||||
current_user.generate_spree_api_key! unless spree_current_user.spree_api_key
|
||||
@spree_api_key = spree_current_user.spree_api_key
|
||||
@producers = Enterprise.managed_by(spree_current_user).is_primary_producer.order(:name)
|
||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).managed_product_enterprises.is_primary_producer.by_name
|
||||
@taxons = Spree::Taxon.order(:name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,12 +4,9 @@ require 'open_food_network/products_and_inventory_report'
|
||||
require 'open_food_network/group_buy_report'
|
||||
require 'open_food_network/order_grouper'
|
||||
require 'open_food_network/customers_report'
|
||||
require 'open_food_network/model_class_from_controller_name'
|
||||
|
||||
Spree::Admin::ReportsController.class_eval do
|
||||
include OpenFoodNetwork::ModelClassFromControllerName
|
||||
|
||||
# Fetches user's distributors, suppliers and order_cycles
|
||||
# Fetches user's distributors, suppliers and order_cycles
|
||||
before_filter :load_data, only: [:customers, :products_and_inventory]
|
||||
|
||||
# Render a partial for orders and fulfillment description
|
||||
@@ -365,9 +362,9 @@ Spree::Admin::ReportsController.class_eval do
|
||||
lis
|
||||
end.flatten
|
||||
#payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments
|
||||
|
||||
|
||||
# -- Prepare form options
|
||||
my_distributors = Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
my_distributors = Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
my_suppliers = Enterprise.is_primary_producer.managed_by(spree_current_user)
|
||||
|
||||
# My distributors and any distributors distributing products I supply
|
||||
@@ -388,21 +385,11 @@ Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
header = ["Producer", "Product", "Variant", "Amount", "Total Units", "Curr. Cost per Unit", "Total Cost", "Status", "Incoming Transport"]
|
||||
|
||||
ovn = OpenFoodNetwork::OptionValueNamer.new()
|
||||
|
||||
columns = [ proc { |line_items| line_items.first.variant.product.supplier.name },
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.sum { |li| li.quantity } },
|
||||
proc { |line_items| ovn.name(OpenStruct.new({
|
||||
unit_value: ( line_items.map{ |li| li.variant.unit_value.nil? }.any? ? 0 : line_items.sum { |li| li.quantity * li.variant.unit_value } ),
|
||||
unit_description: line_items.first.variant.unit_description,
|
||||
product: OpenStruct.new({
|
||||
variant_unit: line_items.first.product.variant_unit,
|
||||
variant_unit_scale: line_items.first.product.variant_unit_scale,
|
||||
variant_unit_name: line_items.first.product.variant_unit_name
|
||||
})
|
||||
}))},
|
||||
proc { |line_items| total_units(line_items) },
|
||||
proc { |line_items| line_items.first.variant.price },
|
||||
proc { |line_items| line_items.sum { |li| li.quantity * li.price } },
|
||||
proc { |line_items| "" },
|
||||
@@ -607,10 +594,10 @@ Spree::Admin::ReportsController.class_eval do
|
||||
def load_data
|
||||
my_distributors = Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
my_suppliers = Enterprise.is_primary_producer.managed_by(spree_current_user)
|
||||
distributors_of_my_products = Enterprise.with_distributed_products_outer.merge(Spree::Product.in_any_supplier(my_suppliers))
|
||||
@distributors = my_distributors | distributors_of_my_products
|
||||
distributors_of_my_products = Enterprise.with_distributed_products_outer.merge(Spree::Product.in_any_supplier(my_suppliers))
|
||||
@distributors = my_distributors | distributors_of_my_products
|
||||
suppliers_of_products_I_distribute = my_distributors.map { |d| Spree::Product.in_distributor(d) }.flatten.map(&:supplier).uniq
|
||||
@suppliers = my_suppliers | suppliers_of_products_I_distribute
|
||||
@suppliers = my_suppliers | suppliers_of_products_I_distribute
|
||||
@order_cycles = OrderCycle.active_or_complete.accessible_by(spree_current_user).order('orders_close_at DESC')
|
||||
end
|
||||
|
||||
@@ -628,4 +615,13 @@ Spree::Admin::ReportsController.class_eval do
|
||||
end
|
||||
reports
|
||||
end
|
||||
|
||||
def total_units(line_items)
|
||||
return " " if line_items.map{ |li| li.variant.unit_value.nil? }.any?
|
||||
total_units = line_items.sum do |li|
|
||||
scale_factor = ( li.product.variant_unit == 'weight' ? 1000 : 1 )
|
||||
li.quantity * li.variant.unit_value / scale_factor
|
||||
end
|
||||
total_units.round(3)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'open_food_network/permissions'
|
||||
|
||||
Spree::Api::ProductsController.class_eval do
|
||||
def managed
|
||||
authorize! :admin, Spree::Product
|
||||
@@ -8,7 +10,11 @@ Spree::Api::ProductsController.class_eval do
|
||||
end
|
||||
|
||||
def bulk_products
|
||||
@products = product_scope.ransack(params[:q]).result.managed_by(current_api_user).page(params[:page]).per(params[:per_page])
|
||||
@products = OpenFoodNetwork::Permissions.new(current_api_user).managed_products.
|
||||
merge(product_scope).
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
|
||||
render text: { products: ActiveModel::ArraySerializer.new(@products, each_serializer: Spree::Api::ProductSerializer), pages: @products.num_pages }.to_json
|
||||
end
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ module Admin
|
||||
admin_inject_json_ams_array("ofn.admin", "all_enterprises", @all_enterprises, Api::Admin::EnterpriseSerializer)
|
||||
end
|
||||
|
||||
def admin_inject_enterprise_relationships
|
||||
admin_inject_json_ams_array "ofn.admin", "enterprise_relationships", @enterprise_relationships, Api::Admin::EnterpriseRelationshipSerializer
|
||||
end
|
||||
|
||||
def admin_inject_enterprise_roles
|
||||
admin_inject_json_ams_array "ofn.admin", "enterpriseRoles", @enterprise_roles, Api::Admin::EnterpriseRoleSerializer
|
||||
end
|
||||
|
||||
@@ -12,8 +12,9 @@ class AngularFormBuilder < ActionView::Helpers::FormBuilder
|
||||
# @object.send(@fields_for_record_name).first.class.to_s.underscore --> enterprise_fee
|
||||
|
||||
value = "{{ #{@object.send(@fields_for_record_name).first.class.to_s.underscore}.#{method} }}"
|
||||
options.reverse_merge!({'id' => angular_id(method)})
|
||||
|
||||
@template.text_field_tag angular_name(method), value, :id => angular_id(method)
|
||||
@template.text_field_tag angular_name(method), value, options
|
||||
end
|
||||
|
||||
def ng_hidden_field(method, options = {})
|
||||
|
||||
@@ -3,8 +3,20 @@ module OrderCyclesHelper
|
||||
@current_order_cycle ||= current_order(false).andand.order_cycle
|
||||
end
|
||||
|
||||
def order_cycle_permitted_enterprises
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user).order_cycle_enterprises
|
||||
end
|
||||
|
||||
def order_cycle_producer_enterprises
|
||||
order_cycle_permitted_enterprises.is_primary_producer.by_name
|
||||
end
|
||||
|
||||
def coordinating_enterprises
|
||||
Enterprise.is_distributor.managed_by(spree_current_user).order('name')
|
||||
order_cycle_hub_enterprises
|
||||
end
|
||||
|
||||
def order_cycle_hub_enterprises
|
||||
order_cycle_permitted_enterprises.is_distributor.by_name
|
||||
end
|
||||
|
||||
def order_cycle_local_remote_class(distributor, order_cycle)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class EnterpriseRelationship < ActiveRecord::Base
|
||||
belongs_to :parent, class_name: 'Enterprise', touch: true
|
||||
belongs_to :child, class_name: 'Enterprise', touch: true
|
||||
has_many :permissions, class_name: 'EnterpriseRelationshipPermission'
|
||||
|
||||
validates_presence_of :parent_id, :child_id
|
||||
validates_uniqueness_of :child_id, scope: :parent_id, message: "^That relationship is already established."
|
||||
@@ -8,9 +9,22 @@ class EnterpriseRelationship < ActiveRecord::Base
|
||||
scope :with_enterprises,
|
||||
joins('LEFT JOIN enterprises AS parent_enterprises ON parent_enterprises.id = enterprise_relationships.parent_id').
|
||||
joins('LEFT JOIN enterprises AS child_enterprises ON child_enterprises.id = enterprise_relationships.child_id')
|
||||
scope :by_name, with_enterprises.order('parent_enterprises.name, child_enterprises.name')
|
||||
|
||||
scope :involving_enterprises, ->(enterprises) {
|
||||
where('parent_id IN (?) OR child_id IN (?)', enterprises, enterprises)
|
||||
}
|
||||
|
||||
scope :permitting, ->(enterprises) { where('child_id IN (?)', enterprises) }
|
||||
|
||||
scope :with_permission, ->(permission) {
|
||||
joins(:permissions).
|
||||
where('enterprise_relationship_permissions.name = ?', permission)
|
||||
}
|
||||
|
||||
scope :by_name, with_enterprises.order('child_enterprises.name, parent_enterprises.name')
|
||||
|
||||
|
||||
def permissions_list=(perms)
|
||||
perms.andand.each { |name| permissions.build name: name }
|
||||
end
|
||||
end
|
||||
|
||||
3
app/models/enterprise_relationship_permission.rb
Normal file
3
app/models/enterprise_relationship_permission.rb
Normal file
@@ -0,0 +1,3 @@
|
||||
class EnterpriseRelationshipPermission < ActiveRecord::Base
|
||||
default_scope order('name')
|
||||
end
|
||||
@@ -43,12 +43,12 @@ class AbilityDecorator
|
||||
# Enterprise User can only access products that they are a supplier for
|
||||
can [:create], Spree::Product
|
||||
can [:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], Spree::Product do |product|
|
||||
user.enterprises.include? product.supplier
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? product.supplier
|
||||
end
|
||||
|
||||
can [:create], Spree::Variant
|
||||
can [:admin, :index, :read, :edit, :update, :search, :destroy], Spree::Variant do |variant|
|
||||
user.enterprises.include? variant.product.supplier
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? variant.product.supplier
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], Spree::ProductProperty
|
||||
@@ -76,6 +76,7 @@ class AbilityDecorator
|
||||
can [:admin, :index, :read, :edit, :update, :bulk_update, :clone], OrderCycle do |order_cycle|
|
||||
user.enterprises.include? order_cycle.coordinator
|
||||
end
|
||||
can [:for_order_cycle], Enterprise
|
||||
|
||||
can [:index, :create], EnterpriseFee
|
||||
can [:admin, :read, :edit, :bulk_update, :destroy], EnterpriseFee do |enterprise_fee|
|
||||
|
||||
@@ -17,6 +17,7 @@ Spree::Product.class_eval do
|
||||
attr_accessible :supplier_id, :primary_taxon_id, :distributor_ids, :product_distributions_attributes, :group_buy, :group_buy_unit_size
|
||||
attr_accessible :variant_unit, :variant_unit_scale, :variant_unit_name, :unit_value, :unit_description, :notes, :images_attributes, :display_as
|
||||
|
||||
validates_associated :master, message: "^Price and On Hand must be valid"
|
||||
validates_presence_of :supplier
|
||||
validates :primary_taxon, presence: { message: "^Product Category can't be blank" }
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ Spree::Variant.class_eval do
|
||||
accepts_nested_attributes_for :images
|
||||
|
||||
validates_presence_of :unit_value,
|
||||
if: -> v { %w(weight volume).include? v.product.variant_unit },
|
||||
if: -> v { %w(weight volume).include? v.product.andand.variant_unit },
|
||||
unless: :is_master
|
||||
|
||||
validates_presence_of :unit_description,
|
||||
if: -> v { v.product.variant_unit.present? && v.unit_value.nil? },
|
||||
if: -> v { v.product.andand.variant_unit.present? && v.unit_value.nil? },
|
||||
unless: :is_master
|
||||
|
||||
before_validation :update_weight_from_unit_value
|
||||
before_validation :update_weight_from_unit_value, if: -> v { v.product.present? }
|
||||
after_save :update_units
|
||||
|
||||
scope :with_order_cycles_inner, joins(exchanges: :order_cycle)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class Api::Admin::EnterpriseRelationshipPermissionSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
class Api::Admin::EnterpriseRelationshipSerializer < ActiveModel::Serializer
|
||||
attributes :id, :parent_id, :parent_name, :child_id, :child_name
|
||||
|
||||
has_many :permissions
|
||||
|
||||
def parent_name
|
||||
object.parent.name
|
||||
end
|
||||
|
||||
def child_name
|
||||
object.child.name
|
||||
end
|
||||
end
|
||||
@@ -27,7 +27,7 @@
|
||||
= f.ng_hidden_field :id
|
||||
= f.ng_collection_select :enterprise_id, @enterprises, :id, :name, 'enterprise_fee.enterprise_id', :include_blank => true
|
||||
%td= f.ng_select :fee_type, enterprise_fee_type_options, 'enterprise_fee.fee_type'
|
||||
%td= f.ng_text_field :name
|
||||
%td= f.ng_text_field :name, { placeholder: 'e.g. packing fee' }
|
||||
%td= f.ng_collection_select :calculator_type, @calculators, :name, :description, 'enterprise_fee.calculator_type', {'class' => 'calculator_type', 'ng-model' => 'calculatorType', 'spree-ensure-calculator-preferences-match-type' => "1"}
|
||||
%td{'ng-bind-html-unsafe-compiled' => 'enterprise_fee.calculator_settings'}
|
||||
%td.actions{'spree-delete-resource' => "1"}
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
:javascript
|
||||
angular.module('ofn.admin').value('enterprise_relationships', #{render partial: "admin/json/enterprise_relationships", object: @enterprise_relationships});
|
||||
angular.module('ofn.admin').value('my_enterprises', #{render partial: "admin/json/enterprises", object: @my_enterprises});
|
||||
angular.module('ofn.admin').value('all_enterprises', #{render partial: "admin/json/enterprises", object: @all_enterprises});
|
||||
= admin_inject_enterprise_relationships
|
||||
= admin_inject_enterprises
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
%td {{ enterprise_relationship.parent_name }}
|
||||
%td permits
|
||||
%td {{ enterprise_relationship.child_name }}
|
||||
%td
|
||||
%ul
|
||||
%li{"ng-repeat" => "permission in enterprise_relationship.permissions"}
|
||||
{{ EnterpriseRelationships.permission_presentation(permission.name) }}
|
||||
%td {{ enterprise_relationship.parent_name }}
|
||||
%td.actions
|
||||
%a.delete-enterprise-relationship.icon-trash.no-text{'ng-click' => 'delete(enterprise_relationship)'}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
%tr
|
||||
%td
|
||||
%select{name: "enterprise_relationship_parent_id", "ng-model" => "parent_id", "ng-options" => "e.id as e.name for e in Enterprises.my_enterprises"}
|
||||
%td permits
|
||||
%td
|
||||
%select{name: "enterprise_relationship_child_id", "ng-model" => "child_id", "ng-options" => "e.id as e.name for e in Enterprises.all_enterprises"}
|
||||
%td
|
||||
%div{"ng-repeat" => "permission in EnterpriseRelationships.all_permissions"}
|
||||
%label
|
||||
%input{type: "checkbox", "ng-model" => "permissions[permission]"}
|
||||
{{ EnterpriseRelationships.permission_presentation(permission) }}
|
||||
%td
|
||||
%select{name: "enterprise_relationship_parent_id", "ng-model" => "parent_id", "ng-options" => "e.id as e.name for e in Enterprises.my_enterprises"}
|
||||
%td.actions
|
||||
%input{type: "button", value: "Create", "ng-click" => "create()"}
|
||||
.errors {{ EnterpriseRelationships.create_errors }}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
object @enterprise_relationship
|
||||
|
||||
attributes :id, :parent_id, :child_id
|
||||
|
||||
node :parent_name do |enterprise_relationship|
|
||||
enterprise_relationship.parent.name
|
||||
end
|
||||
|
||||
node :child_name do |enterprise_relationship|
|
||||
enterprise_relationship.child.name
|
||||
end
|
||||
@@ -1,2 +0,0 @@
|
||||
collection @enterprise_relationships
|
||||
extends "admin/json/enterprise_relationship"
|
||||
@@ -23,4 +23,4 @@
|
||||
|
||||
= f.submit 'Add fee', 'ng-click' => 'addExchangeFee($event, exchange)'
|
||||
%td.actions
|
||||
%a{'ng-click' => 'removeExchange($event, exchange)', :class => "icon-trash no-text"}
|
||||
%a{'ng-click' => 'removeExchange($event, exchange)', :class => "icon-trash no-text remove-exchange"}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
%tr.products{'ng-show' => 'exchange.showProducts'}
|
||||
= render 'exchange_supplied_products_form'
|
||||
|
||||
= select_tag :new_supplier_id, options_from_collection_for_select(Enterprise.is_primary_producer.managed_by(spree_current_user).by_name, :id, :name), {'ng-model' => 'new_supplier_id'}
|
||||
= select_tag :new_supplier_id, options_from_collection_for_select(order_cycle_producer_enterprises, :id, :name), {'ng-model' => 'new_supplier_id'}
|
||||
= f.submit 'Add supplier', 'ng-click' => 'addSupplier($event)'
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
%tr.products{'ng-show' => 'exchange.showProducts'}
|
||||
= render 'exchange_distributed_products_form'
|
||||
|
||||
= select_tag :new_distributor_id, options_from_collection_for_select(Enterprise.is_distributor.managed_by(spree_current_user).by_name, :id, :name), {'ng-model' => 'new_distributor_id'}
|
||||
= select_tag :new_distributor_id, options_from_collection_for_select(order_cycle_hub_enterprises, :id, :name), {'ng-model' => 'new_distributor_id'}
|
||||
= f.submit 'Add distributor', 'ng-click' => 'addDistributor($event)'
|
||||
|
||||
.actions
|
||||
|
||||
@@ -9,7 +9,7 @@ r.element :order_cycle, @order_cycle do
|
||||
r.element :id
|
||||
end
|
||||
|
||||
r.list_of :exchanges, @order_cycle.exchanges.managed_by(spree_current_user).order('id ASC') do |exchange|
|
||||
r.list_of :exchanges, OpenFoodNetwork::Permissions.new(spree_current_user).order_cycle_exchanges(@order_cycle).order('id ASC') do |exchange|
|
||||
r.element :id
|
||||
r.element :sender_id
|
||||
r.element :receiver_id
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
{{ summary() | printArray }}
|
||||
.small-4.medium-2.columns.text-right
|
||||
%span.accordion-up
|
||||
%em
|
||||
%em
|
||||
%small Hide
|
||||
%i.ofn-i_053-point-up
|
||||
%i.ofn-i_053-point-up
|
||||
%span.accordion-down
|
||||
%em
|
||||
%em
|
||||
%small Expand
|
||||
%i.ofn-i_052-point-down
|
||||
%i.ofn-i_052-point-down
|
||||
|
||||
= f.fields_for :bill_address, @order.bill_address do |ba|
|
||||
.row
|
||||
@@ -40,14 +40,14 @@
|
||||
|
||||
.small-6.columns
|
||||
= ba.select :state_id, @order.billing_address.country.states.map{|c|[c.name, c.id]}, {include_blank: false},
|
||||
"ng-model" => "order.bill_address.state_id"
|
||||
"ng-model" => "order.bill_address.state_id", required: true
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input "Postcode", "order.bill_address.zipcode"
|
||||
|
||||
.small-6.columns.right
|
||||
= ba.select :country_id, available_countries.map{|c|[c.name, c.id]},
|
||||
{include_blank: false}, "ng-model" => "order.bill_address.country_id"
|
||||
"ng-model" => "order.bill_address.country_id", required: true
|
||||
|
||||
.row
|
||||
.small-12.columns.text-right
|
||||
|
||||
@@ -9,23 +9,23 @@
|
||||
%i.ofn-i_051-check-big
|
||||
Your details
|
||||
|
||||
%accordion-group{"is-open" => "accordion.details",
|
||||
%accordion-group{"is-open" => "accordion.details",
|
||||
"ng-class" => "{valid: details.$valid, open: accordion.details}"}
|
||||
%accordion-heading
|
||||
.row
|
||||
.small-8.medium-10.columns
|
||||
%em
|
||||
%em
|
||||
%small
|
||||
{{ summary() | printArray }}
|
||||
.small-4.medium-2.columns.text-right
|
||||
%span.accordion-up
|
||||
%em
|
||||
%em
|
||||
%small Hide
|
||||
%i.ofn-i_053-point-up
|
||||
%i.ofn-i_053-point-up
|
||||
%span.accordion-down
|
||||
%em
|
||||
%em
|
||||
%small Expand
|
||||
%i.ofn-i_052-point-down
|
||||
%i.ofn-i_052-point-down
|
||||
|
||||
.row
|
||||
.small-6.columns
|
||||
@@ -36,10 +36,10 @@
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input 'Email', 'order.email', type: :email, "ofn-focus" => "accordion['details']"
|
||||
|
||||
|
||||
.small-6.columns
|
||||
= validated_input 'Phone', 'order.bill_address.phone'
|
||||
|
||||
|
||||
.row
|
||||
.small-12.columns.text-right
|
||||
%button.primary{"ng-disabled" => "details.$invalid", "ng-click" => "next($event)"} Next
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
= f_form_for current_order, url: main_app.update_checkout_path,
|
||||
html: {name: "checkout",
|
||||
= f_form_for current_order, url: main_app.update_checkout_path,
|
||||
html: {name: "checkout",
|
||||
id: "checkout_form",
|
||||
novalidate: true,
|
||||
name: "checkout"} do |f|
|
||||
@@ -10,8 +10,8 @@
|
||||
angular.module('Darkswarm').value('order', #{render "checkout/order"})
|
||||
|
||||
%div
|
||||
/ %h3.text-center.pad-top
|
||||
/ Checkout from
|
||||
/ %h3.text-center.pad-top
|
||||
/ Checkout from
|
||||
/ = current_distributor.name
|
||||
|
||||
= render partial: "checkout/details", locals: {f: f}
|
||||
@@ -19,7 +19,7 @@
|
||||
= render partial: "checkout/shipping", locals: {f: f}
|
||||
= render partial: "checkout/payment", locals: {f: f}
|
||||
%p
|
||||
%button.button.primary{type: :submit,
|
||||
%button.button.primary{type: :submit,
|
||||
"ng-click" => "purchase($event)",
|
||||
"ng-disabled" => "checkout.$invalid"}
|
||||
Place order now
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%fieldset#payment
|
||||
%ng-form{"ng-controller" => "PaymentCtrl", name: "payment"}
|
||||
|
||||
%h5{"ng-class" => "{valid: payment.$valid, dirty: payment.$dirty}"}
|
||||
%h5{"ng-class" => "{valid: payment.$valid, dirty: payment.$dirty}"}
|
||||
%span.right
|
||||
%label.label.round.alert.right
|
||||
%i.ofn-i_009-close
|
||||
@@ -14,16 +14,16 @@
|
||||
%accordion-heading
|
||||
.row
|
||||
.small-8.medium-10.columns
|
||||
%em
|
||||
%em
|
||||
%small
|
||||
{{ Checkout.paymentMethod().name }}
|
||||
.small-4.medium-2.columns.text-right
|
||||
%span.accordion-up
|
||||
%em
|
||||
%em
|
||||
%small Hide
|
||||
%i.ofn-i_053-point-up
|
||||
%i.ofn-i_053-point-up
|
||||
%span.accordion-down
|
||||
%em
|
||||
%em
|
||||
%small Expand
|
||||
%i.ofn-i_052-point-down
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"ng-model" => "order.payment_method_id"
|
||||
= method.name
|
||||
|
||||
.row{"ng-show" => "order.payment_method_id == #{method.id}"}
|
||||
.row{"ng-if" => "order.payment_method_id == #{method.id}"}
|
||||
.small-12.columns
|
||||
= render partial: "spree/checkout/payment/#{method.method_type}", :locals => { :payment_method => method }
|
||||
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
%accordion-heading
|
||||
.row
|
||||
.small-8.medium-10.columns
|
||||
%em
|
||||
%em
|
||||
%small
|
||||
{{ Checkout.shippingMethod().name }}
|
||||
.small-4.medium-2.columns.text-right
|
||||
%span.accordion-up
|
||||
%em
|
||||
%em
|
||||
%small Hide
|
||||
%i.ofn-i_053-point-up
|
||||
%i.ofn-i_053-point-up
|
||||
%span.accordion-down
|
||||
%em
|
||||
%em
|
||||
%small Expand
|
||||
%i.ofn-i_052-point-down
|
||||
|
||||
@@ -61,13 +61,14 @@
|
||||
.small-6.columns
|
||||
= validated_input "City", "order.ship_address.city"
|
||||
.small-6.columns
|
||||
= sa.select :state_id, @order.shipping_address.country.states.map{|c|[c.name, c.id]}
|
||||
= sa.select :state_id, @order.shipping_address.country.states.map{|c|[c.name, c.id]}, {include_blank: false},
|
||||
"ng-model" => "order.ship_address.state_id", required: true
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input "Postcode", "order.ship_address.zipcode"
|
||||
.small-6.columns.right
|
||||
= sa.select :country_id, available_countries.map{|c|[c.name, c.id]},
|
||||
{include_blank: false}
|
||||
"ng-model" => "order.ship_address.country_id", required: true
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input "First Name", "order.ship_address.firstname"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
= inject_enterprises
|
||||
= inject_enterprises
|
||||
|
||||
.darkswarm
|
||||
- content_for :order_cycle_form do
|
||||
|
||||
|
||||
%closing Checkout now
|
||||
%p
|
||||
%p
|
||||
Order ready for
|
||||
%strong
|
||||
= pickup_time current_order_cycle
|
||||
|
||||
= render partial: "shopping_shared/details"
|
||||
|
||||
|
||||
%accordion{"close-others" => "true"}
|
||||
%checkout.row{"ng-controller" => "CheckoutCtrl"}
|
||||
.small-12.medium-8.large-9.columns
|
||||
|
||||
@@ -33,12 +33,15 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
namespace :admin do
|
||||
resources :order_cycles do
|
||||
post :bulk_update, :on => :collection, :as => :bulk_update
|
||||
post :bulk_update, on: :collection, as: :bulk_update
|
||||
get :clone, on: :member
|
||||
end
|
||||
|
||||
resources :enterprises do
|
||||
post :bulk_update, :on => :collection, :as => :bulk_update
|
||||
collection do
|
||||
get :for_order_cycle
|
||||
post :bulk_update, as: :bulk_update
|
||||
end
|
||||
|
||||
resources :producer_properties do
|
||||
post :update_positions, on: :collection
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class CreateEnterpriseRelationshipPermissions < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :enterprise_relationship_permissions do |t|
|
||||
t.references :enterprise_relationship
|
||||
t.string :name, null: false
|
||||
end
|
||||
|
||||
add_index :enterprise_relationship_permissions, :enterprise_relationship_id, name: 'index_erp_on_erid'
|
||||
add_foreign_key :enterprise_relationship_permissions, :enterprise_relationships, name: 'erp_enterprise_relationship_id_fk'
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class PreventDuplicateEnterpriseRoles < ActiveRecord::Migration
|
||||
def change
|
||||
add_index :enterprise_roles, [:enterprise_id, :user_id], unique: true
|
||||
end
|
||||
end
|
||||
14
db/schema.rb
14
db/schema.rb
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20140815065014) do
|
||||
ActiveRecord::Schema.define(:version => 20140826043521) do
|
||||
|
||||
create_table "adjustment_metadata", :force => true do |t|
|
||||
t.integer "adjustment_id"
|
||||
@@ -207,6 +207,13 @@ ActiveRecord::Schema.define(:version => 20140815065014) do
|
||||
add_index "enterprise_groups_enterprises", ["enterprise_group_id"], :name => "index_enterprise_groups_enterprises_on_enterprise_group_id"
|
||||
add_index "enterprise_groups_enterprises", ["enterprise_id"], :name => "index_enterprise_groups_enterprises_on_enterprise_id"
|
||||
|
||||
create_table "enterprise_relationship_permissions", :force => true do |t|
|
||||
t.integer "enterprise_relationship_id"
|
||||
t.string "name", :null => false
|
||||
end
|
||||
|
||||
add_index "enterprise_relationship_permissions", ["enterprise_relationship_id"], :name => "index_erp_on_erid"
|
||||
|
||||
create_table "enterprise_relationships", :force => true do |t|
|
||||
t.integer "parent_id"
|
||||
t.integer "child_id"
|
||||
@@ -221,6 +228,7 @@ ActiveRecord::Schema.define(:version => 20140815065014) do
|
||||
t.integer "enterprise_id"
|
||||
end
|
||||
|
||||
add_index "enterprise_roles", ["enterprise_id", "user_id"], :name => "index_enterprise_roles_on_enterprise_id_and_user_id", :unique => true
|
||||
add_index "enterprise_roles", ["enterprise_id"], :name => "index_enterprise_roles_on_enterprise_id"
|
||||
add_index "enterprise_roles", ["user_id", "enterprise_id"], :name => "index_enterprise_roles_on_user_id_and_enterprise_id", :unique => true
|
||||
add_index "enterprise_roles", ["user_id"], :name => "index_enterprise_roles_on_user_id"
|
||||
@@ -555,9 +563,9 @@ ActiveRecord::Schema.define(:version => 20140815065014) 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
|
||||
|
||||
@@ -1052,6 +1060,8 @@ ActiveRecord::Schema.define(:version => 20140815065014) do
|
||||
add_foreign_key "enterprise_groups_enterprises", "enterprise_groups", name: "enterprise_groups_enterprises_enterprise_group_id_fk"
|
||||
add_foreign_key "enterprise_groups_enterprises", "enterprises", name: "enterprise_groups_enterprises_enterprise_id_fk"
|
||||
|
||||
add_foreign_key "enterprise_relationship_permissions", "enterprise_relationships", name: "erp_enterprise_relationship_id_fk"
|
||||
|
||||
add_foreign_key "enterprise_relationships", "enterprises", name: "enterprise_relationships_child_id_fk", column: "child_id"
|
||||
add_foreign_key "enterprise_relationships", "enterprises", name: "enterprise_relationships_parent_id_fk", column: "parent_id"
|
||||
|
||||
|
||||
60
lib/open_food_network/permissions.rb
Normal file
60
lib/open_food_network/permissions.rb
Normal file
@@ -0,0 +1,60 @@
|
||||
module OpenFoodNetwork
|
||||
class Permissions
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
# Find enterprises that an admin is allowed to add to an order cycle
|
||||
def order_cycle_enterprises
|
||||
managed_and_related_enterprises_with :add_to_order_cycle
|
||||
end
|
||||
|
||||
# Find the exchanges of an order cycle that an admin can manage
|
||||
def order_cycle_exchanges(order_cycle)
|
||||
enterprises = managed_enterprises + related_enterprises_with(:add_to_order_cycle)
|
||||
order_cycle.exchanges.to_enterprises(enterprises).from_enterprises(enterprises)
|
||||
end
|
||||
|
||||
def managed_products
|
||||
managed_enterprise_products_ids = managed_enterprise_products.pluck :id
|
||||
permitted_enterprise_products_ids = related_enterprise_products.pluck :id
|
||||
Spree::Product.where('id IN (?)', managed_enterprise_products_ids + permitted_enterprise_products_ids)
|
||||
end
|
||||
|
||||
def managed_product_enterprises
|
||||
managed_and_related_enterprises_with :manage_products
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def managed_enterprises
|
||||
Enterprise.managed_by(@user)
|
||||
end
|
||||
|
||||
def related_enterprises_with(permission)
|
||||
parent_ids = EnterpriseRelationship.
|
||||
permitting(managed_enterprises).
|
||||
with_permission(permission).
|
||||
pluck(:parent_id)
|
||||
|
||||
Enterprise.where('id IN (?)', parent_ids)
|
||||
end
|
||||
|
||||
def managed_and_related_enterprises_with(permission)
|
||||
managed_enterprise_ids = managed_enterprises.pluck :id
|
||||
permitted_enterprise_ids = related_enterprises_with(permission).pluck :id
|
||||
|
||||
Enterprise.where('id IN (?)', managed_enterprise_ids + permitted_enterprise_ids)
|
||||
end
|
||||
|
||||
|
||||
def managed_enterprise_products
|
||||
Spree::Product.managed_by(@user)
|
||||
end
|
||||
|
||||
def related_enterprise_products
|
||||
Spree::Product.where('supplier_id IN (?)', related_enterprises_with(:manage_products))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,4 +6,4 @@ set -e
|
||||
|
||||
echo "drop database open_food_network_dev" | psql -h localhost -U ofn open_food_network_test
|
||||
echo "create database open_food_network_dev" | psql -h localhost -U ofn open_food_network_test
|
||||
zcat $1 |psql -h localhost -U ofn open_food_network_dev
|
||||
gunzip -c $1 |psql -h localhost -U ofn open_food_network_dev
|
||||
|
||||
@@ -1,11 +1,28 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Admin::ProductsController do
|
||||
context "Creating a new product" do
|
||||
describe "updating a product we do not have access to" do
|
||||
let(:s_managed) { create(:enterprise) }
|
||||
let(:s_unmanaged) { create(:enterprise) }
|
||||
let(:p) { create(:simple_product, supplier: s_unmanaged, name: 'Peas') }
|
||||
|
||||
before do
|
||||
login_as_admin
|
||||
login_as_enterprise_user [s_managed]
|
||||
spree_post :bulk_update, {"products" => [{"id" => p.id, "name" => "Pine nuts"}]}
|
||||
end
|
||||
|
||||
it "denies access" do
|
||||
response.should redirect_to "http://test.host/unauthorized"
|
||||
end
|
||||
|
||||
it "does not update any product" do
|
||||
p.reload.name.should_not == "Pine nuts"
|
||||
end
|
||||
end
|
||||
|
||||
context "creating a new product" do
|
||||
before { login_as_admin }
|
||||
|
||||
it "redirects to bulk_edit when the user hits 'create'" do
|
||||
s = create(:supplier_enterprise)
|
||||
t = create(:taxon)
|
||||
|
||||
@@ -729,20 +729,29 @@ feature %q{
|
||||
end
|
||||
|
||||
context "as an enterprise manager" do
|
||||
let(:s1) { create(:supplier_enterprise, name: 'First Supplier') }
|
||||
let(:s2) { create(:supplier_enterprise, name: 'Another Supplier') }
|
||||
let(:s3) { create(:supplier_enterprise, name: 'Yet Another Supplier') }
|
||||
let(:d1) { create(:distributor_enterprise, name: 'First Distributor') }
|
||||
let(:d2) { create(:distributor_enterprise, name: 'Another Distributor') }
|
||||
let!(:product_supplied) { create(:product, supplier: s1, price: 10.0, on_hand: 6) }
|
||||
let!(:product_not_supplied) { create(:product, supplier: s3) }
|
||||
let(:product_supplied_inactive) { create(:product, supplier: s1, price: 10.0, on_hand: 6, available_on: 1.week.from_now) }
|
||||
let(:supplier_managed1) { create(:supplier_enterprise, name: 'Supplier Managed 1') }
|
||||
let(:supplier_managed2) { create(:supplier_enterprise, name: 'Supplier Managed 2') }
|
||||
let(:supplier_unmanaged) { create(:supplier_enterprise, name: 'Supplier Unmanaged') }
|
||||
let(:supplier_permitted) { create(:supplier_enterprise, name: 'Supplier Permitted') }
|
||||
let(:distributor_managed) { create(:distributor_enterprise, name: 'Distributor Managed') }
|
||||
let(:distributor_unmanaged) { create(:distributor_enterprise, name: 'Distributor Unmanaged') }
|
||||
let!(:product_supplied) { create(:product, supplier: supplier_managed1, price: 10.0, on_hand: 6) }
|
||||
let!(:product_not_supplied) { create(:product, supplier: supplier_unmanaged) }
|
||||
let!(:product_supplied_permitted) { create(:product, name: 'Product Permitted', supplier: supplier_permitted, price: 10.0, on_hand: 6) }
|
||||
let(:product_supplied_inactive) { create(:product, supplier: supplier_managed1, price: 10.0, on_hand: 6, available_on: 1.week.from_now) }
|
||||
|
||||
before(:each) do
|
||||
let!(:supplier_permitted_relationship) do
|
||||
create(:enterprise_relationship, parent: supplier_permitted, child: supplier_managed1,
|
||||
permissions_list: [:manage_products])
|
||||
end
|
||||
|
||||
use_short_wait
|
||||
|
||||
before do
|
||||
@enterprise_user = create_enterprise_user
|
||||
@enterprise_user.enterprise_roles.build(enterprise: s1).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: s2).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: d1).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: supplier_managed1).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: supplier_managed2).save
|
||||
@enterprise_user.enterprise_roles.build(enterprise: distributor_managed).save
|
||||
|
||||
login_to_admin_as @enterprise_user
|
||||
end
|
||||
@@ -751,14 +760,15 @@ feature %q{
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_field 'product_name', with: product_supplied.name
|
||||
expect(page).to have_field 'product_name', with: product_supplied_permitted.name
|
||||
expect(page).to have_no_field 'product_name', with: product_not_supplied.name
|
||||
end
|
||||
|
||||
it "shows only suppliers that I manage" do
|
||||
it "shows only suppliers that I manage or have permission to" do
|
||||
visit '/admin/products/bulk_edit'
|
||||
|
||||
expect(page).to have_select 'producer', with_options: [s1.name, s2.name], selected: s1.name
|
||||
expect(page).to have_no_select 'producer', with_options: [s3.name]
|
||||
expect(page).to have_select 'producer', with_options: [supplier_managed1.name, supplier_managed2.name, supplier_permitted.name], selected: supplier_managed1.name
|
||||
expect(page).to have_no_select 'producer', with_options: [supplier_unmanaged.name]
|
||||
end
|
||||
|
||||
it "shows inactive products that I supply" do
|
||||
@@ -770,32 +780,34 @@ feature %q{
|
||||
end
|
||||
|
||||
it "allows me to update a product" do
|
||||
p = product_supplied
|
||||
p = product_supplied_permitted
|
||||
|
||||
visit '/admin/products/bulk_edit'
|
||||
first("div#columns_dropdown", :text => "COLUMNS").click
|
||||
first("div#columns_dropdown div.menu div.menu_item", text: "Available On").click
|
||||
|
||||
expect(page).to have_field "product_name", with: p.name
|
||||
expect(page).to have_select "producer", 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_field "on_hand", with: "6"
|
||||
within "tr#p_#{p.id}" do
|
||||
expect(page).to have_field "product_name", with: p.name
|
||||
expect(page).to have_select "producer", 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(s2.name, :from => 'producer')
|
||||
fill_in "available_on", with: (Date.today-3).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"
|
||||
fill_in "product_name", with: "Big Bag Of Potatoes"
|
||||
select(supplier_managed2.name, :from => 'producer')
|
||||
fill_in "available_on", with: (Date.today-3).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"
|
||||
end
|
||||
|
||||
click_button 'Save Changes'
|
||||
expect(page.find("#update-status-message")).to have_content "Changes saved."
|
||||
|
||||
p.reload
|
||||
expect(p.name).to eq "Big Bag Of Potatoes"
|
||||
expect(p.supplier).to eq s2
|
||||
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
|
||||
|
||||
@@ -14,8 +14,9 @@ feature %q{
|
||||
scenario "listing relationships" do
|
||||
# Given some enterprises with relationships
|
||||
e1, e2, e3, e4 = create(:enterprise), create(:enterprise), create(:enterprise), create(:enterprise)
|
||||
create(:enterprise_relationship, parent: e1, child: e2)
|
||||
create(:enterprise_relationship, parent: e3, child: e4)
|
||||
create(:enterprise_relationship, parent: e1, child: e2, permissions_list: [:add_to_order_cycle])
|
||||
create(:enterprise_relationship, parent: e2, child: e3, permissions_list: [:manage_products])
|
||||
create(:enterprise_relationship, parent: e3, child: e4, permissions_list: [:add_to_order_cycle, :manage_products])
|
||||
|
||||
# When I go to the relationships page
|
||||
click_link 'Enterprises'
|
||||
@@ -23,8 +24,10 @@ feature %q{
|
||||
|
||||
# Then I should see the relationships
|
||||
within('table#enterprise-relationships') do
|
||||
page.should have_relationship e1, e2
|
||||
page.should have_relationship e3, e4
|
||||
page.should have_relationship e1, e2, ['can add to order cycle']
|
||||
page.should have_relationship e2, e3, ['can manage the products of']
|
||||
page.should have_relationship e3, e4,
|
||||
['can add to order cycle', 'can manage the products of']
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,11 +38,17 @@ feature %q{
|
||||
|
||||
visit admin_enterprise_relationships_path
|
||||
select 'One', from: 'enterprise_relationship_parent_id'
|
||||
|
||||
check 'can add to order cycle'
|
||||
check 'can manage the products of'
|
||||
uncheck 'can manage the products of'
|
||||
select 'Two', from: 'enterprise_relationship_child_id'
|
||||
click_button 'Create'
|
||||
|
||||
page.should have_relationship e1, e2
|
||||
EnterpriseRelationship.where(parent_id: e1, child_id: e2).should be_present
|
||||
page.should have_relationship e1, e2, ['can add to order cycle']
|
||||
er = EnterpriseRelationship.where(parent_id: e1, child_id: e2).first
|
||||
er.should be_present
|
||||
er.permissions.map(&:name).should == ['add_to_order_cycle']
|
||||
end
|
||||
|
||||
|
||||
@@ -108,7 +117,9 @@ feature %q{
|
||||
|
||||
private
|
||||
|
||||
def have_relationship(parent, child)
|
||||
have_table_row [parent.name, 'permits', child.name, '']
|
||||
def have_relationship(parent, child, perms=[])
|
||||
perms = perms.join(' ') || 'permits'
|
||||
|
||||
have_table_row [child.name, perms, parent.name, '']
|
||||
end
|
||||
end
|
||||
|
||||
@@ -436,26 +436,35 @@ feature %q{
|
||||
|
||||
context "as an enterprise user" do
|
||||
|
||||
let(:supplier1) { create(:supplier_enterprise, name: 'First Supplier') }
|
||||
let(:supplier2) { create(:supplier_enterprise, name: 'Another Supplier') }
|
||||
let(:distributor1) { create(:distributor_enterprise, name: 'First Distributor') }
|
||||
let(:distributor2) { create(:distributor_enterprise, name: 'Another Distributor') }
|
||||
let!(:distributor1_fee) { create(:enterprise_fee, enterprise: distributor1, name: 'First Distributor Fee') }
|
||||
before(:each) do
|
||||
product = create(:product, supplier: supplier1)
|
||||
product.distributors << distributor1
|
||||
product.save!
|
||||
let!(:supplier_managed) { create(:supplier_enterprise, name: 'Managed supplier') }
|
||||
let!(:supplier_unmanaged) { create(:supplier_enterprise, name: 'Unmanaged supplier') }
|
||||
let!(:supplier_permitted) { create(:supplier_enterprise, name: 'Permitted supplier') }
|
||||
let!(:distributor_managed) { create(:distributor_enterprise, name: 'Managed distributor') }
|
||||
let!(:distributor_unmanaged) { create(:distributor_enterprise, name: 'Unmanaged Distributor') }
|
||||
let!(:distributor_permitted) { create(:distributor_enterprise, name: 'Permitted distributor') }
|
||||
let!(:distributor_managed_fee) { create(:enterprise_fee, enterprise: distributor_managed, name: 'Managed distributor fee') }
|
||||
let!(:supplier_permitted_relationship) do
|
||||
create(:enterprise_relationship, parent: supplier_permitted, child: supplier_managed,
|
||||
permissions_list: [:add_to_order_cycle])
|
||||
end
|
||||
let!(:distributor_permitted_relationship) do
|
||||
create(:enterprise_relationship, parent: distributor_permitted, child: distributor_managed,
|
||||
permissions_list: [:add_to_order_cycle])
|
||||
end
|
||||
let!(:product_managed) { create(:product, supplier: supplier_managed) }
|
||||
let!(:product_permitted) { create(:product, supplier: supplier_permitted) }
|
||||
|
||||
before do
|
||||
@new_user = create_enterprise_user
|
||||
@new_user.enterprise_roles.build(enterprise: supplier1).save
|
||||
@new_user.enterprise_roles.build(enterprise: distributor1).save
|
||||
@new_user.enterprise_roles.build(enterprise: supplier_managed).save
|
||||
@new_user.enterprise_roles.build(enterprise: distributor_managed).save
|
||||
|
||||
login_to_admin_as @new_user
|
||||
end
|
||||
|
||||
scenario "viewing a list of order cycles I am coordinating" do
|
||||
oc_user_coordinating = create(:simple_order_cycle, { suppliers: [supplier1, supplier2], coordinator: supplier1, distributors: [distributor1, distributor2], name: 'Order Cycle 1' } )
|
||||
oc_for_other_user = create(:simple_order_cycle, { coordinator: supplier2, name: 'Order Cycle 2' } )
|
||||
oc_user_coordinating = create(:simple_order_cycle, { suppliers: [supplier_managed, supplier_unmanaged], coordinator: supplier_managed, distributors: [distributor_managed, distributor_unmanaged], name: 'Order Cycle 1' } )
|
||||
oc_for_other_user = create(:simple_order_cycle, { coordinator: supplier_unmanaged, name: 'Order Cycle 2' } )
|
||||
|
||||
click_link "Order Cycles"
|
||||
|
||||
@@ -464,8 +473,8 @@ feature %q{
|
||||
page.should_not have_content oc_for_other_user.name
|
||||
|
||||
# The order cycle should not show enterprises that I don't manage
|
||||
page.should_not have_selector 'td.suppliers', text: supplier2.name
|
||||
page.should_not have_selector 'td.distributors', text: distributor2.name
|
||||
page.should_not have_selector 'td.suppliers', text: supplier_unmanaged.name
|
||||
page.should_not have_selector 'td.distributors', text: distributor_unmanaged.name
|
||||
end
|
||||
|
||||
scenario "creating a new order cycle" do
|
||||
@@ -476,57 +485,84 @@ feature %q{
|
||||
fill_in 'order_cycle_orders_open_at', with: '2012-11-06 06:00:00'
|
||||
fill_in 'order_cycle_orders_close_at', with: '2012-11-13 17:00:00'
|
||||
|
||||
select 'First Supplier', from: 'new_supplier_id'
|
||||
select 'Managed supplier', from: 'new_supplier_id'
|
||||
click_button 'Add supplier'
|
||||
select 'Permitted supplier', from: 'new_supplier_id'
|
||||
click_button 'Add supplier'
|
||||
|
||||
select 'First Distributor', from: 'order_cycle_coordinator_id'
|
||||
click_button 'Add coordinator fee'
|
||||
select 'First Distributor Fee', from: 'order_cycle_coordinator_fee_0_id'
|
||||
select_incoming_variant supplier_managed, 0, product_managed.master
|
||||
select_incoming_variant supplier_permitted, 1, product_permitted.master
|
||||
|
||||
select 'First Distributor', from: 'new_distributor_id'
|
||||
select 'Managed distributor', from: 'order_cycle_coordinator_id'
|
||||
click_button 'Add coordinator fee'
|
||||
select 'Managed distributor fee', from: 'order_cycle_coordinator_fee_0_id'
|
||||
|
||||
select 'Managed distributor', from: 'new_distributor_id'
|
||||
click_button 'Add distributor'
|
||||
select 'Permitted distributor', from: 'new_distributor_id'
|
||||
click_button 'Add distributor'
|
||||
|
||||
# Should only have suppliers / distributors listed which the user can manage
|
||||
within "#new_supplier_id" do
|
||||
page.should_not have_content supplier2.name
|
||||
end
|
||||
within "#new_distributor_id" do
|
||||
page.should_not have_content distributor2.name
|
||||
end
|
||||
within "#order_cycle_coordinator_id" do
|
||||
page.should_not have_content distributor2.name
|
||||
page.should_not have_content supplier1.name
|
||||
page.should_not have_content supplier2.name
|
||||
# Should only have suppliers / distributors listed which the user is managing or
|
||||
# has E2E permission to add products to order cycles
|
||||
page.should_not have_select 'new_supplier_id', with_options: [supplier_unmanaged.name]
|
||||
page.should_not have_select 'new_distributor_id', with_options: [distributor_unmanaged.name]
|
||||
|
||||
[distributor_unmanaged.name, supplier_managed.name, supplier_unmanaged.name].each do |enterprise_name|
|
||||
page.should_not have_select 'order_cycle_coordinator_id', with_options: [enterprise_name]
|
||||
end
|
||||
|
||||
click_button 'Create'
|
||||
|
||||
flash_message.should == "Your order cycle has been created."
|
||||
order_cycle = OrderCycle.find_by_name('My order cycle')
|
||||
order_cycle.coordinator.should == distributor1
|
||||
order_cycle.suppliers.sort.should == [supplier_managed, supplier_permitted].sort
|
||||
order_cycle.coordinator.should == distributor_managed
|
||||
order_cycle.distributors.sort.should == [distributor_managed, distributor_permitted].sort
|
||||
end
|
||||
|
||||
scenario "editing an order cycle" do
|
||||
oc = create(:simple_order_cycle, { suppliers: [supplier1, supplier2], coordinator: supplier1, distributors: [distributor1, distributor2], name: 'Order Cycle 1' } )
|
||||
scenario "editing an order cycle does not affect exchanges we don't manage" do
|
||||
oc = create(:simple_order_cycle, { suppliers: [supplier_managed, supplier_permitted, supplier_unmanaged], coordinator: supplier_managed, distributors: [distributor_managed, distributor_permitted, distributor_unmanaged], name: 'Order Cycle 1' } )
|
||||
|
||||
visit edit_admin_order_cycle_path(oc)
|
||||
|
||||
# I should not see exchanges for supplier2 or distributor2
|
||||
page.all('tr.supplier').count.should == 1
|
||||
page.all('tr.distributor').count.should == 1
|
||||
# I should not see exchanges for supplier_unmanaged or distributor_unmanaged
|
||||
page.all('tr.supplier').count.should == 2
|
||||
page.all('tr.distributor').count.should == 2
|
||||
|
||||
# When I save, then those exchanges should remain
|
||||
click_button 'Update'
|
||||
page.should have_content "Your order cycle has been updated."
|
||||
|
||||
oc.reload
|
||||
oc.suppliers.sort.should == [supplier1, supplier2]
|
||||
oc.coordinator.should == supplier1
|
||||
oc.distributors.sort.should == [distributor1, distributor2]
|
||||
oc.suppliers.sort.should == [supplier_managed, supplier_permitted, supplier_unmanaged].sort
|
||||
oc.coordinator.should == supplier_managed
|
||||
oc.distributors.sort.should == [distributor_managed, distributor_permitted, distributor_unmanaged].sort
|
||||
end
|
||||
|
||||
scenario "editing an order cycle" do
|
||||
oc = create(:simple_order_cycle, { suppliers: [supplier_managed, supplier_permitted, supplier_unmanaged], coordinator: supplier_managed, distributors: [distributor_managed, distributor_permitted, distributor_unmanaged], name: 'Order Cycle 1' } )
|
||||
|
||||
visit edit_admin_order_cycle_path(oc)
|
||||
|
||||
# When I remove all the exchanges and save
|
||||
page.find("tr.supplier-#{supplier_managed.id} a.remove-exchange").click
|
||||
page.find("tr.supplier-#{supplier_permitted.id} a.remove-exchange").click
|
||||
page.find("tr.distributor-#{distributor_managed.id} a.remove-exchange").click
|
||||
page.find("tr.distributor-#{distributor_permitted.id} a.remove-exchange").click
|
||||
click_button 'Update'
|
||||
|
||||
# Then the exchanges should be removed
|
||||
page.should have_content "Your order cycle has been updated."
|
||||
|
||||
oc.reload
|
||||
oc.suppliers.should == [supplier_unmanaged]
|
||||
oc.coordinator.should == supplier_managed
|
||||
oc.distributors.should == [distributor_unmanaged]
|
||||
end
|
||||
|
||||
|
||||
scenario "cloning an order cycle" do
|
||||
oc = create(:simple_order_cycle)
|
||||
oc = create(:simple_order_cycle, coordinator: distributor_managed)
|
||||
|
||||
click_link "Order Cycles"
|
||||
first('a.clone-order-cycle').click
|
||||
@@ -539,4 +575,11 @@ feature %q{
|
||||
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def select_incoming_variant(supplier, exchange_no, variant)
|
||||
page.find("table.exchanges tr.supplier-#{supplier.id} td.products input").click
|
||||
check "order_cycle_incoming_exchange_#{exchange_no}_variants_#{variant.id}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,15 +15,15 @@ feature "As a consumer I want to check out my cart", js: true do
|
||||
let(:product) { create(:simple_product, supplier: supplier) }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor) }
|
||||
|
||||
|
||||
before do
|
||||
ActionMailer::Base.deliveries.clear
|
||||
add_enterprise_fee enterprise_fee
|
||||
set_order order
|
||||
add_product_to_cart
|
||||
end
|
||||
|
||||
it "shows the current distributor on checkout" do
|
||||
visit checkout_path
|
||||
visit checkout_path
|
||||
page.should have_content distributor.name
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ feature "As a consumer I want to check out my cart", js: true do
|
||||
page.should have_content "Donkeys"
|
||||
end
|
||||
|
||||
context "When shipping method requires an address" do
|
||||
context "when shipping method requires an address" do
|
||||
before do
|
||||
toggle_shipping
|
||||
choose sm1.name
|
||||
@@ -79,53 +79,23 @@ feature "As a consumer I want to check out my cart", js: true do
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
visit checkout_path
|
||||
checkout_as_guest
|
||||
toggle_payment
|
||||
end
|
||||
|
||||
it "shows all available payment methods" do
|
||||
page.should have_content pm1.name
|
||||
page.should have_content pm2.name
|
||||
page.should have_content pm3.name
|
||||
end
|
||||
|
||||
describe "Purchasing" do
|
||||
it "takes us to the order confirmation page when we submit a complete form" do
|
||||
ActionMailer::Base.deliveries.clear
|
||||
toggle_shipping
|
||||
choose sm2.name
|
||||
context "on the checkout page with payments open" do
|
||||
before do
|
||||
visit checkout_path
|
||||
checkout_as_guest
|
||||
toggle_payment
|
||||
choose pm1.name
|
||||
toggle_details
|
||||
within "#details" do
|
||||
fill_in "First Name", with: "Will"
|
||||
fill_in "Last Name", with: "Marshall"
|
||||
fill_in "Email", with: "test@test.com"
|
||||
fill_in "Phone", with: "0468363090"
|
||||
end
|
||||
toggle_billing
|
||||
within "#billing" do
|
||||
fill_in "Address", with: "123 Your Face"
|
||||
select "Australia", from: "Country"
|
||||
select "Victoria", from: "State"
|
||||
fill_in "City", with: "Melbourne"
|
||||
fill_in "Postcode", with: "3066"
|
||||
|
||||
end
|
||||
place_order
|
||||
page.should have_content "Your order has been processed successfully"
|
||||
ActionMailer::Base.deliveries.length.should == 1
|
||||
email = ActionMailer::Base.deliveries.last
|
||||
site_name = Spree::Config[:site_name]
|
||||
email.subject.should include "#{site_name} Order Confirmation"
|
||||
end
|
||||
|
||||
context "with basic details filled" do
|
||||
before do
|
||||
it "shows all available payment methods" do
|
||||
page.should have_content pm1.name
|
||||
page.should have_content pm2.name
|
||||
page.should have_content pm3.name
|
||||
end
|
||||
|
||||
describe "purchasing" do
|
||||
it "takes us to the order confirmation page when we submit a complete form" do
|
||||
toggle_shipping
|
||||
choose sm1.name
|
||||
choose sm2.name
|
||||
toggle_payment
|
||||
choose pm1.name
|
||||
toggle_details
|
||||
@@ -137,56 +107,111 @@ feature "As a consumer I want to check out my cart", js: true do
|
||||
end
|
||||
toggle_billing
|
||||
within "#billing" do
|
||||
fill_in "City", with: "Melbourne"
|
||||
fill_in "Postcode", with: "3066"
|
||||
fill_in "Address", with: "123 Your Face"
|
||||
select "Australia", from: "Country"
|
||||
select "Victoria", from: "State"
|
||||
end
|
||||
toggle_shipping
|
||||
check "Shipping address same as billing address?"
|
||||
end
|
||||
fill_in "City", with: "Melbourne"
|
||||
fill_in "Postcode", with: "3066"
|
||||
|
||||
it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do
|
||||
end
|
||||
place_order
|
||||
page.should have_content "Your order has been processed successfully"
|
||||
ActionMailer::Base.deliveries.length.should == 2
|
||||
email = ActionMailer::Base.deliveries.last
|
||||
site_name = Spree::Config[:site_name]
|
||||
email.subject.should include "#{site_name} Order Confirmation"
|
||||
end
|
||||
|
||||
context "with a credit card payment method" do
|
||||
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::Gateway::Bogus") }
|
||||
|
||||
it "takes us to the order confirmation page when submitted with a valid credit card" do
|
||||
context "with basic details filled" do
|
||||
before do
|
||||
toggle_shipping
|
||||
choose sm1.name
|
||||
toggle_payment
|
||||
fill_in 'Card Number', with: "4111111111111111"
|
||||
select 'February', from: 'secrets.card_month'
|
||||
select (Date.today.year+1).to_s, from: 'secrets.card_year'
|
||||
fill_in 'Security Code', with: '123'
|
||||
choose pm1.name
|
||||
toggle_details
|
||||
within "#details" do
|
||||
fill_in "First Name", with: "Will"
|
||||
fill_in "Last Name", with: "Marshall"
|
||||
fill_in "Email", with: "test@test.com"
|
||||
fill_in "Phone", with: "0468363090"
|
||||
end
|
||||
toggle_billing
|
||||
within "#billing" do
|
||||
fill_in "City", with: "Melbourne"
|
||||
fill_in "Postcode", with: "3066"
|
||||
fill_in "Address", with: "123 Your Face"
|
||||
select "Australia", from: "Country"
|
||||
select "Victoria", from: "State"
|
||||
end
|
||||
toggle_shipping
|
||||
check "Shipping address same as billing address?"
|
||||
end
|
||||
|
||||
it "takes us to the order confirmation page when submitted with 'same as billing address' checked" do
|
||||
place_order
|
||||
page.should have_content "Your order has been processed successfully"
|
||||
|
||||
# Order should have a payment with the correct amount
|
||||
o = Spree::Order.complete.first
|
||||
o.payments.first.amount.should == 11.23
|
||||
end
|
||||
|
||||
it "shows the payment processing failed message when submitted with an invalid credit card" do
|
||||
toggle_payment
|
||||
fill_in 'Card Number', with: "9999999988887777"
|
||||
select 'February', from: 'secrets.card_month'
|
||||
select (Date.today.year+1).to_s, from: 'secrets.card_year'
|
||||
fill_in 'Security Code', with: '123'
|
||||
context "with a credit card payment method" do
|
||||
let!(:pm1) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::Gateway::Bogus") }
|
||||
|
||||
place_order
|
||||
page.should have_content "Payment could not be processed, please check the details you entered"
|
||||
it "takes us to the order confirmation page when submitted with a valid credit card" do
|
||||
toggle_payment
|
||||
fill_in 'Card Number', with: "4111111111111111"
|
||||
select 'February', from: 'secrets.card_month'
|
||||
select (Date.today.year+1).to_s, from: 'secrets.card_year'
|
||||
fill_in 'Security Code', with: '123'
|
||||
|
||||
# Does not show duplicate shipping fee
|
||||
visit checkout_path
|
||||
page.all("th", text: "Shipping").count.should == 1
|
||||
place_order
|
||||
page.should have_content "Your order has been processed successfully"
|
||||
|
||||
# Order should have a payment with the correct amount
|
||||
o = Spree::Order.complete.first
|
||||
o.payments.first.amount.should == 11.23
|
||||
end
|
||||
|
||||
it "shows the payment processing failed message when submitted with an invalid credit card" do
|
||||
toggle_payment
|
||||
fill_in 'Card Number', with: "9999999988887777"
|
||||
select 'February', from: 'secrets.card_month'
|
||||
select (Date.today.year+1).to_s, from: 'secrets.card_year'
|
||||
fill_in 'Security Code', with: '123'
|
||||
|
||||
place_order
|
||||
page.should have_content "Payment could not be processed, please check the details you entered"
|
||||
|
||||
# Does not show duplicate shipping fee
|
||||
visit checkout_path
|
||||
page.all("th", text: "Shipping").count.should == 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when the customer has a pre-set shipping and billing address" do
|
||||
before do
|
||||
# Load up the customer's order and give them a shipping and billing address
|
||||
# This is equivalent to when the customer has ordered before and their addresses
|
||||
# are pre-populated.
|
||||
o = Spree::Order.last
|
||||
o.ship_address = build(:address)
|
||||
o.bill_address = build(:address)
|
||||
o.save!
|
||||
end
|
||||
|
||||
it "checks out successfully" do
|
||||
visit checkout_path
|
||||
checkout_as_guest
|
||||
choose sm2.name
|
||||
toggle_payment
|
||||
choose pm1.name
|
||||
|
||||
place_order
|
||||
page.should have_content "Your order has been processed successfully"
|
||||
ActionMailer::Base.deliveries.length.should == 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
describe "enterprise relationships", ->
|
||||
EnterpriseRelationships = null
|
||||
enterprise_relationships = []
|
||||
|
||||
beforeEach ->
|
||||
module "ofn.admin"
|
||||
module ($provide) ->
|
||||
$provide.value "enterprise_relationships", enterprise_relationships
|
||||
null
|
||||
|
||||
beforeEach inject (_EnterpriseRelationships_) ->
|
||||
EnterpriseRelationships = _EnterpriseRelationships_
|
||||
|
||||
it "presents permission names", ->
|
||||
expect(EnterpriseRelationships.permission_presentation("add_to_order_cycle")).toEqual "can add to order cycle"
|
||||
expect(EnterpriseRelationships.permission_presentation("manage_products")).toEqual "can manage the products of"
|
||||
@@ -7,6 +7,7 @@ describe 'Products service', ->
|
||||
CurrentHubMock = {}
|
||||
currentOrder = null
|
||||
product = null
|
||||
productWithImage = null
|
||||
|
||||
beforeEach ->
|
||||
product =
|
||||
@@ -16,6 +17,14 @@ describe 'Products service', ->
|
||||
price: 11
|
||||
master: {}
|
||||
variants: []
|
||||
productWithImage =
|
||||
supplier:
|
||||
id: 9
|
||||
master: {}
|
||||
variants: []
|
||||
images: [
|
||||
large_url: 'foo.png'
|
||||
]
|
||||
currentOrder =
|
||||
line_items: []
|
||||
|
||||
@@ -62,6 +71,11 @@ describe 'Products service', ->
|
||||
expect(Products.products[0].primaryImage).toBeUndefined()
|
||||
expect(Products.products[0].primaryImageOrMissing).toEqual "/assets/noimage/small.png"
|
||||
|
||||
it "sets largeImage", ->
|
||||
$httpBackend.expectGET("/shop/products").respond([productWithImage])
|
||||
$httpBackend.flush()
|
||||
expect(Products.products[0].largeImage).toEqual("foo.png")
|
||||
|
||||
describe "determining the price to display for a product", ->
|
||||
it "displays the product price when the product does not have variants", ->
|
||||
$httpBackend.expectGET("/shop/products").respond([product])
|
||||
|
||||
@@ -327,7 +327,7 @@ describe 'OrderCycle services', ->
|
||||
inject ($injector, _$httpBackend_)->
|
||||
Enterprise = $injector.get('Enterprise')
|
||||
$httpBackend = _$httpBackend_
|
||||
$httpBackend.whenGET('/admin/enterprises.json').respond [
|
||||
$httpBackend.whenGET('/admin/enterprises/for_order_cycle.json').respond [
|
||||
{id: 1, name: 'One', supplied_products: [1, 2]}
|
||||
{id: 2, name: 'Two', supplied_products: [3, 4]}
|
||||
{id: 3, name: 'Three', supplied_products: [5, 6]}
|
||||
|
||||
132
spec/lib/open_food_network/permissions_spec.rb
Normal file
132
spec/lib/open_food_network/permissions_spec.rb
Normal file
@@ -0,0 +1,132 @@
|
||||
require 'open_food_network/permissions'
|
||||
|
||||
module OpenFoodNetwork
|
||||
describe Permissions do
|
||||
let(:user) { double(:user) }
|
||||
let(:permissions) { Permissions.new(user) }
|
||||
let(:permission) { 'one' }
|
||||
let(:e1) { create(:enterprise) }
|
||||
let(:e2) { create(:enterprise) }
|
||||
|
||||
describe "finding enterprises that can be added to an order cycle" do
|
||||
let(:e) { double(:enterprise) }
|
||||
|
||||
it "returns managed and related enterprises with add_to_order_cycle permission" do
|
||||
permissions.
|
||||
should_receive(:managed_and_related_enterprises_with).
|
||||
with(:add_to_order_cycle).
|
||||
and_return([e])
|
||||
|
||||
permissions.order_cycle_enterprises.should == [e]
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding exchanges of an order cycle that an admin can manage" do
|
||||
let(:oc) { create(:simple_order_cycle) }
|
||||
let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2) }
|
||||
|
||||
before do
|
||||
permissions.stub(:managed_enterprises) { [] }
|
||||
permissions.stub(:related_enterprises_with) { [] }
|
||||
end
|
||||
|
||||
it "returns exchanges involving enterprises managed by the user" do
|
||||
permissions.stub(:managed_enterprises) { [e1, e2] }
|
||||
permissions.order_cycle_exchanges(oc).should == [ex]
|
||||
end
|
||||
|
||||
it "returns exchanges involving enterprises with E2E permission" do
|
||||
permissions.stub(:related_enterprises_with) { [e1, e2] }
|
||||
permissions.order_cycle_exchanges(oc).should == [ex]
|
||||
end
|
||||
|
||||
it "does not return exchanges involving only the sender" do
|
||||
permissions.stub(:managed_enterprises) { [e1] }
|
||||
permissions.order_cycle_exchanges(oc).should == []
|
||||
end
|
||||
|
||||
it "does not return exchanges involving only the receiver" do
|
||||
permissions.stub(:managed_enterprises) { [e2] }
|
||||
permissions.order_cycle_exchanges(oc).should == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding managed products" do
|
||||
let!(:p1) { create(:simple_product) }
|
||||
let!(:p2) { create(:simple_product) }
|
||||
|
||||
before do
|
||||
permissions.stub(:managed_enterprise_products) { Spree::Product.where('1=0') }
|
||||
permissions.stub(:related_enterprise_products) { Spree::Product.where('1=0') }
|
||||
end
|
||||
|
||||
it "returns products produced by managed enterprises" do
|
||||
permissions.stub(:managed_enterprise_products) { Spree::Product.where(id: p1) }
|
||||
permissions.managed_products.should == [p1]
|
||||
end
|
||||
|
||||
it "returns products produced by permitted enterprises" do
|
||||
permissions.stub(:related_enterprise_products) { Spree::Product.where(id: p2) }
|
||||
permissions.managed_products.should == [p2]
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding enterprises that we manage products for" do
|
||||
let(:e) { double(:enterprise) }
|
||||
|
||||
it "returns managed and related enterprises with manage_products permission" do
|
||||
permissions.
|
||||
should_receive(:managed_and_related_enterprises_with).
|
||||
with(:manage_products).
|
||||
and_return([e])
|
||||
|
||||
permissions.managed_product_enterprises.should == [e]
|
||||
end
|
||||
end
|
||||
|
||||
########################################
|
||||
|
||||
describe "finding related enterprises with a particular permission" do
|
||||
let!(:er) { create(:enterprise_relationship, parent: e1, child: e2, permissions_list: [permission]) }
|
||||
|
||||
it "returns the enterprises" do
|
||||
permissions.stub(:managed_enterprises) { e2 }
|
||||
permissions.send(:related_enterprises_with, permission).should == [e1]
|
||||
end
|
||||
|
||||
it "returns an empty array when there are none" do
|
||||
permissions.stub(:managed_enterprises) { e1 }
|
||||
permissions.send(:related_enterprises_with, permission).should == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding enterprises that are managed or with a particular permission" do
|
||||
before do
|
||||
permissions.stub(:managed_enterprises) { Enterprise.where('1=0') }
|
||||
permissions.stub(:related_enterprises_with) { Enterprise.where('1=0') }
|
||||
end
|
||||
|
||||
it "returns managed enterprises" do
|
||||
permissions.should_receive(:managed_enterprises) { Enterprise.where(id: e1) }
|
||||
permissions.send(:managed_and_related_enterprises_with, permission).should == [e1]
|
||||
end
|
||||
|
||||
it "returns permitted enterprises" do
|
||||
permissions.should_receive(:related_enterprises_with).with(permission).
|
||||
and_return(Enterprise.where(id: e2))
|
||||
permissions.send(:managed_and_related_enterprises_with, permission).should == [e2]
|
||||
end
|
||||
end
|
||||
|
||||
describe "finding the supplied products of related enterprises" do
|
||||
let!(:e) { create(:enterprise) }
|
||||
let!(:p) { create(:simple_product, supplier: e) }
|
||||
|
||||
it "returns supplied products" do
|
||||
permissions.should_receive(:related_enterprises_with).with(:manage_products) { [e] }
|
||||
|
||||
permissions.send(:related_enterprise_products).should == [p]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,10 +6,10 @@ describe EnterpriseRelationship do
|
||||
let(:e2) { create(:enterprise, name: 'B') }
|
||||
let(:e3) { create(:enterprise, name: 'C') }
|
||||
|
||||
it "sorts by parent, child enterprise name" do
|
||||
er1 = create(:enterprise_relationship, parent: e1, child: e3)
|
||||
er2 = create(:enterprise_relationship, parent: e2, child: e1)
|
||||
er3 = create(:enterprise_relationship, parent: e1, child: e2)
|
||||
it "sorts by child, parent enterprise name" do
|
||||
er1 = create(:enterprise_relationship, parent: e3, child: e1)
|
||||
er2 = create(:enterprise_relationship, parent: e1, child: e2)
|
||||
er3 = create(:enterprise_relationship, parent: e2, child: e1)
|
||||
|
||||
EnterpriseRelationship.by_name.should == [er3, er1, er2]
|
||||
end
|
||||
@@ -29,5 +29,38 @@ describe EnterpriseRelationship do
|
||||
EnterpriseRelationship.involving_enterprises([e3]).should == []
|
||||
end
|
||||
end
|
||||
|
||||
describe "creating with a permission list" 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
|
||||
end
|
||||
|
||||
it "does nothing when the list is nil" do
|
||||
er = EnterpriseRelationship.create! parent: e1, child: e2, permissions_list: nil
|
||||
er.reload
|
||||
er.permissions.should be_empty
|
||||
end
|
||||
end
|
||||
|
||||
it "finds relationships that grant permissions to some enterprises" do
|
||||
er1 = create(:enterprise_relationship, parent: e2, child: e1)
|
||||
er2 = create(:enterprise_relationship, parent: e3, child: e2)
|
||||
er3 = create(:enterprise_relationship, parent: e1, child: e3)
|
||||
|
||||
EnterpriseRelationship.permitting([e1, e2]).sort.should == [er1, er2]
|
||||
end
|
||||
|
||||
it "finds relationships that grant a particular permission" do
|
||||
er1 = create(:enterprise_relationship, parent: e1, child: e2,
|
||||
permissions_list: ['one', 'two'])
|
||||
er2 = create(:enterprise_relationship, parent: e2, child: e3,
|
||||
permissions_list: ['two', 'three'])
|
||||
er3 = create(:enterprise_relationship, parent: e3, child: e1,
|
||||
permissions_list: ['three', 'four'])
|
||||
|
||||
EnterpriseRelationship.with_permission('two').sort.should == [er1, er2].sort
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,14 +51,17 @@ module Spree
|
||||
# create enterprises
|
||||
let(:s1) { create(:supplier_enterprise) }
|
||||
let(:s2) { create(:supplier_enterprise) }
|
||||
let(:s_related) { create(:supplier_enterprise) }
|
||||
let(:d1) { create(:distributor_enterprise) }
|
||||
let(:d2) { create(:distributor_enterprise) }
|
||||
|
||||
let(:p1) { create(:product, supplier: s1, distributors:[d1, d2]) }
|
||||
let(:p2) { create(:product, supplier: s2, distributors:[d1, d2]) }
|
||||
let(:p_related) { create(:product, supplier: s_related) }
|
||||
|
||||
let(:er1) { create(:enterprise_relationship, parent: s1, child: d1) }
|
||||
let(:er2) { create(:enterprise_relationship, parent: d1, child: s1) }
|
||||
let(:er_p) { create(:enterprise_relationship, parent: s_related, child: s1, permissions_list: [:manage_products]) }
|
||||
|
||||
subject { user }
|
||||
let(:user) { nil }
|
||||
@@ -74,12 +77,20 @@ module Spree
|
||||
|
||||
let(:order) {create(:order)}
|
||||
|
||||
it "should be able to read/write their enterprises' products" do
|
||||
it "should be able to read/write their enterprises' products and variants" do
|
||||
should have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p1)
|
||||
should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p1.master)
|
||||
end
|
||||
|
||||
it "should not be able to read/write other enterprises' products" do
|
||||
it "should be able to read/write related enterprises' products and variants with manage_products permission" do
|
||||
er_p
|
||||
should have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p_related)
|
||||
should have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p_related.master)
|
||||
end
|
||||
|
||||
it "should not be able to read/write other enterprises' products and variants" do
|
||||
should_not have_ability([:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :destroy], for: p2)
|
||||
should_not have_ability([:admin, :index, :read, :edit, :update, :search, :destroy], for: p2.master)
|
||||
end
|
||||
|
||||
it "should not be able to access admin actions on orders" do
|
||||
@@ -247,7 +258,7 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
context 'Enterprise manager' do
|
||||
context 'enterprise manager' do
|
||||
let (:user) do
|
||||
user = create(:user)
|
||||
user.spree_roles = []
|
||||
@@ -264,7 +275,7 @@ module Spree
|
||||
end
|
||||
|
||||
it 'should have the ability administrate and create enterpises' do
|
||||
should have_ability([:admin, :index, :create], for: Enterprise)
|
||||
should have_ability([:admin, :index, :for_order_cycle, :create], for: Enterprise)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,12 +27,20 @@ module Spree
|
||||
product.should_not be_valid
|
||||
end
|
||||
|
||||
it "should default available_on to now" do
|
||||
it "defaults available_on to now" do
|
||||
Timecop.freeze
|
||||
product = Product.new
|
||||
product.available_on.should == Time.now
|
||||
end
|
||||
|
||||
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.on_hand = "10,000"
|
||||
product.save.should be_false
|
||||
end
|
||||
|
||||
context "when the product has variants" do
|
||||
let(:product) do
|
||||
product = create(:simple_product)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "admin/enterprises/index.rabl" do
|
||||
describe "admin/enterprises/for_order_cycle.rabl" do
|
||||
let(:enterprise) { create(:distributor_enterprise) }
|
||||
let!(:product) { create(:simple_product, supplier: enterprise) }
|
||||
let!(:deleted_product) { create(:simple_product, supplier: enterprise, deleted_at: 1.day.ago) }
|
||||
let(:render) { Rabl.render([enterprise], 'admin/enterprises/index', view_path: 'app/views', scope: RablHelper::FakeContext.instance) }
|
||||
let(:render) { Rabl.render([enterprise], 'admin/enterprises/for_order_cycle', view_path: 'app/views', scope: RablHelper::FakeContext.instance) }
|
||||
|
||||
describe "supplied products" do
|
||||
it "does not render deleted products" do
|
||||
@@ -1,23 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "admin/json/_enterprise_relationships.json.rabl" do
|
||||
let(:parent) { create(:enterprise) }
|
||||
let(:child) { create(:enterprise) }
|
||||
let(:enterprise_relationship) { create(:enterprise_relationship, parent: parent, child: child) }
|
||||
let(:render) { Rabl.render([enterprise_relationship], 'admin/json/enterprise_relationships', view_path: 'app/views', scope: RablHelper::FakeContext.instance) }
|
||||
|
||||
it "renders a list of enterprise relationships" do
|
||||
render.should have_json_type(Array).at_path ''
|
||||
render.should have_json_type(Object).at_path '0'
|
||||
end
|
||||
|
||||
it "renders enterprise ids" do
|
||||
render.should be_json_eql(parent.id).at_path '0/parent_id'
|
||||
render.should be_json_eql(child.id).at_path '0/child_id'
|
||||
end
|
||||
|
||||
it "renders enterprise names" do
|
||||
render.should be_json_eql(parent.name.to_json).at_path '0/parent_name'
|
||||
render.should be_json_eql(child.name.to_json).at_path '0/child_name'
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user